When installing host OS for running private cloud, I've installed GIT, Vagrant, VirtualBox, NodeJS, and Nginx on the host OS. So, keep notes here:



sudo apt-get update
sudo apt-get install -y libcurl4-gnutls-dev libexpat1-dev gettext libz-dev libssl-dev build-essential
wget https://github.com/git/git/archive/v1.8.5.tar.gz
tar -xvf v1.8.5.tar.gz
cd git-1.8.5/
make prefix=/usr/local all
sudo make prefix=/usr/local install



Edit /etc/apt/sources.list, by adding following repository list

deb http://download.virtualbox.org/virtualbox/debian saucy contrib
deb http://download.virtualbox.org/virtualbox/debian raring contrib
deb http://download.virtualbox.org/virtualbox/debian quantal contrib
deb http://download.virtualbox.org/virtualbox/debian precise contrib
deb http://download.virtualbox.org/virtualbox/debian lucid contrib non-free
deb http://download.virtualbox.org/virtualbox/debian wheezy contrib
deb http://download.virtualbox.org/virtualbox/debian squeeze contrib non-free

Installation scripts

wget -q http://download.virtualbox.org/virtualbox/debian/oracle_vbox.asc -O- | sudo apt-key add -
sudo apt-get update
sudo apt-get -y install virtualbox-4.3
wget http://files.vagrantup.com/packages/a40522f5fabccb9ddabad03d836e120ff5d14093/vagrant_1.3.5_x86_64.deb
dpkg -i vagrant_1.3.5_x86_64.deb

Test scripts

sudo su
wget http://files.vagrantup.com/precise64.box
vagrant box add precise64 precise64.box
mkdir tmp
cd tmp
vagrant init precise64
vagrant up
vagrant ssh


sudo apt-get install -y build-essential openssl libssl-dev pkg-config 
wget http://nodejs.org/dist/v0.10.22/node-v0.10.22.tar.gz
tar -xvf node-v0.10.22.tar.gz
cd node-v0.10.22
sudo su
./configure --prefix=/opt/node && make && sudo make install


Install one nginx from ubuntu repository and use its init script, and replace it with
our compiled version

sudo su
apt-get update && apt-get dist-upgrade -y
apt-get install -y nginx
apt-get install -y build-essential libpcre3 libpcre3-dev libpcrecpp0 libssl-dev zlib1g-dev
apt-get install -y libgeoip-dev
wget http://nginx.org/download/nginx-1.5.6.tar.gz
tar -xvf nginx-1.5.6.tar.gz
cd nginx-1.5.6
./configure \

    --prefix=/etc/nginx \

    --sbin-path=/usr/local/sbin \

    --conf-path=/etc/nginx/nginx.conf \

    --error-log-path=/var/log/nginx/error.log \

    --http-log-path=/var/log/nginx/access.log \

    --pid-path=/var/run/nginx.pid \

    --lock-path=/var/run/nginx.lock \

    --http-client-body-temp-path=/var/cache/nginx/client_temp \

    --http-proxy-temp-path=/var/cache/nginx/proxy_temp \

    --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp \

    --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp \

    --http-scgi-temp-path=/var/cache/nginx/scgi_temp \

    --user=nginx \

    --group=nginx \

    --with-http_ssl_module \

    --with-http_spdy_module \

    --with-http_addition_module \

    --with-http_realip_module \

    --with-http_sub_module \

    --with-http_dav_module \

    --with-http_flv_module \

    --with-http_mp4_module \

    --with-http_gunzip_module \

    --with-http_gzip_static_module \

    --with-http_geoip_module \

    --with-http_random_index_module \

    --with-http_secure_link_module \

    --with-http_stub_status_module \

    --with-mail \

    --with-mail_ssl_module \

    --with-file-aio \

make install

Quick Note


sudo su
yum install scons gcc -y
yum install fuse-devel -y
yum install rpmbuild -y

Download RPM source and build

wget http://download1.rpmfusion.org/free/el/updates/6/SRPMS/exfat-utils-1.0.1-1.el6.src.rpm
wget http://download1.rpmfusion.org/free/el/updates/6/SRPMS/fuse-exfat-1.0.1-1.el6.src.rpm
rpm -ivh fuse-exfat-1.0.1-1.el6.src.rpm exfat-utils-1.0.1-1.el6.src.rpm
cd ./rpmbuild/SPECS
rpmbuild -ba fuse-exfat.spec
rpmbuild -ba exfat-utils.spec
cd ../RPMS/x86_64/
rpm -ivh fuse-exfat-1.0.1-1.el6.x86_64.rpm exfat-utils-1.0.1-1.el6.x86_64.rpm
ln -s /usr/sbin/mount.exfat /sbin/mount.exfat


mount -t exfat /dev/sdc1 /mnt/archives/

看到了 我在用的 QuickLook plugins, 提醒我要安裝一些 QuickLook plugins, 便於快速檢閱某些檔案. 所以興起寫這篇文章, 把我安裝的過程記錄下來, 避免忘記.


Markdown 格式的檔案 (*.md, *.markdown)

Source Codes

JSON 格式的檔案 (*.json)

CSV 格式的檔案 (*.csv)

壓縮格式的檔案 (*.rar, *.tar.bz2, *.tgz, *.zip, *.7z...)

請注意, BetterZip plugin 是不需要安裝 BetterZip app 的, 所以這也是免費的方案.

無附檔名的檔案 (e.g. LICENSE, README, COPYRIGHT, ...)

Mindmap 格式的檔案 (*.mm)

假如 plugin 沒有生效, 可以打 qlmanage -r 強制重新載入 plugin.


針對 QLColorCode, 我做了一些客製化.

首先, 需要能夠顯示 line numbers

defaults write org.n8gray.QLColorCode extraHLFlags '--linenumbers'

再來, 使用一個我看得順眼的 color scheme

defaults write org.n8gray.QLColorCode hlTheme darkside

這個 darkside scheme 檔案需要放在 /Library/QuickLook/QLColorCode.qlgenerator/Contents/Resources/highlight/share/highlight/themes/ 目錄下, 檔名為 darkside.style. 內容如下:


然後跑 qlmanage -r 強制重新載入 plugin, 這樣看到的 plugin 會長這個樣子:


20131023 後記

後來發現了 Adobe 的 Source Code Pro 字體, 看起來超舒服的. 我的 Sublime Text 2 也改用這個字體了. 請到 github 下載字型檔, 然後通過 Font Book 安裝到系統中.

順便把 QLColorCode 的設定一併修改掉, 以下的命令執行一下:

defaults write org.n8gray.QLColorCode font 'Source Code Pro'
defaults write org.n8gray.QLColorCode fontSizePoints 9

這是現在 Quick Look 的長相:

在 VMWare Player 上面安裝了 CentOS 6.4 64bits, 然後想安裝 Nginx 1.5.0, 包含 GeoIP 以及 SPDY 的功能.


uname -a
cat /etc/redhat-release


安裝必要的 packages (由於有些 repo 沒有 GeoIP package, 所以需要增加新的 repo)

yum install gcc automake make -y
yum install pcre-devel zlib-devel openssl-devel -y
rpm -Uvh http://dl.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm
yum install GeoIP-devel GeoIP -y

下載與編譯 Nginx 1.5.0

wget http://nginx.org/download/nginx-1.5.0.tar.gz
tar xvzf nginx-1.5.0.tar.gz
cd nginx-1.5.0
./configure \
    --prefix=/etc/nginx \
    --sbin-path=/usr/sbin/nginx \
    --conf-path=/etc/nginx/nginx.conf \
    --error-log-path=/var/log/nginx/error.log \
    --http-log-path=/var/log/nginx/access.log \
    --pid-path=/var/run/nginx.pid \
    --lock-path=/var/run/nginx.lock \
    --http-client-body-temp-path=/var/cache/nginx/client_temp \
    --http-proxy-temp-path=/var/cache/nginx/proxy_temp \
    --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp \
    --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp \
    --http-scgi-temp-path=/var/cache/nginx/scgi_temp \
    --user=nginx \
    --group=nginx \
    --with-http_ssl_module \
    --with-http_spdy_module \
    --with-http_addition_module \
    --with-http_realip_module \
    --with-http_sub_module \
    --with-http_dav_module \
    --with-http_flv_module \
    --with-http_mp4_module \
    --with-http_gunzip_module \
    --with-http_gzip_static_module \
    --with-http_geoip_module \
    --with-http_random_index_module \
    --with-http_secure_link_module \
    --with-http_stub_status_module \
    --with-mail \
    --with-mail_ssl_module \
    --with-file-aio \

sudo make install

準備 GeoIP database

cd /etc/nginx/
mkdir /etc/nginx/geoip
cd /etc/nginx/geoip/
wget http://geolite.maxmind.com/download/geoip/database/GeoLiteCountry/GeoIP.dat.gz
gunzip GeoIP.dat.gz
wget http://geolite.maxmind.com/download/geoip/database/GeoLiteCity.dat.gz
gunzip GeoLiteCity.dat.gz


useradd nginx
mkdir -p /var/cache/nginx/client_temp
echo /usr/sbin/nginx > /etc/rc.local

第三行是把 Nginx 加入到啟動腳本中.

再來, 修改 /etc/sysconfig/iptables, 增加一行 -A INPUT -m state --state NEW -m tcp -p tcp --dport 80 -j ACCEPT 開放 port 80. 然後重新啟動 iptables 防火牆:

/etc/init.d/iptables restart

Nginx 設定

修改 /etc/nginx.conf, 新增以下幾行:

http {
        geoip_country /etc/nginx/geoip/GeoIP.dat;       # the country IP database
        geoip_city    /etc/nginx/geoip/GeoLiteCity.dat; # the city IP database
        log_format  main '$geoip_city_country_code - $geoip_city - $remote_addr - $remote_user '
                     '[$time_local] "$request" '
                     '$status $body_bytes_sent "$http_referer" '
                     '"$http_user_agent" "$http_x_forwarded_for"';
    access_log    /var/log/nginx/access.log  main;
    error_log     /var/log/nginx/error.log main;
    include /etc/nginx/proxy.conf;

修改 /etc/nginx/fastcgi_params:

fastcgi_param GEOIP_COUNTRY_CODE $geoip_country_code;
fastcgi_param GEOIP_COUNTRY_CODE3 $geoip_country_code3;
fastcgi_param GEOIP_COUNTRY_NAME $geoip_country_name;

fastcgi_param GEOIP_CITY_COUNTRY_CODE $geoip_city_country_code;
fastcgi_param GEOIP_CITY_COUNTRY_CODE3 $geoip_city_country_code3;
fastcgi_param GEOIP_CITY_COUNTRY_NAME $geoip_city_country_name;
fastcgi_param GEOIP_REGION $geoip_region;
fastcgi_param GEOIP_CITY $geoip_city;
fastcgi_param GEOIP_POSTAL_CODE $geoip_postal_code;
fastcgi_param GEOIP_CITY_CONTINENT_CODE $geoip_city_continent_code;
fastcgi_param GEOIP_LATITUDE $geoip_latitude;
fastcgi_param GEOIP_LONGITUDE $geoip_longitude;

增加 /etc/nginx/proxy.conf:

### SET GEOIP Variables ###
proxy_set_header GEOIP_COUNTRY_CODE $geoip_country_code;
proxy_set_header GEOIP_COUNTRY_CODE3 $geoip_country_code3;
proxy_set_header GEOIP_COUNTRY_NAME $geoip_country_name;

proxy_set_header GEOIP_CITY_COUNTRY_CODE $geoip_city_country_code;
proxy_set_header GEOIP_CITY_COUNTRY_CODE3 $geoip_city_country_code3;
proxy_set_header GEOIP_CITY_COUNTRY_NAME $geoip_city_country_name;
proxy_set_header GEOIP_REGION $geoip_region;
proxy_set_header GEOIP_CITY $geoip_city;
proxy_set_header GEOIP_POSTAL_CODE $geoip_postal_code;
proxy_set_header GEOIP_CITY_CONTINENT_CODE $geoip_city_continent_code;
proxy_set_header GEOIP_LATITUDE $geoip_latitude;
proxy_set_header GEOIP_LONGITUDE $geoip_longitude;


有空的時候, 應該要:

  • 寫 chef cookbook 來自動化上面這些操作.
  • 測試 SPDY
  • 測試 WebSocket


我是一個很健忘的人..., 我的老婆也常常抱怨這件事情...

所以, 開了 Administration 這一個分類, 記錄一些我肯定記不住的事情/命令/...

Recently, I am interested in SBC (single-board computer) and need to prepare a Linux development environment because many utilities/tools/packages are ONLY available on Linux (such as cross-compiler). I have 2 Mac mini and 1 MBP, and I want to share the Linux development environment among these computers with minimal efforts. Then, it comes to me to utilize Vagrant and VirtualBox to automate Linux environment setup.

Then, I meet several problems... Here I explain how those problems are solved, and the results are committed to github.

USB SD-Card Reader

Now popular SBCs use SD-card as storage to store Linux or Android, so it's necessary to use dd command to write Linux/Android images onto SD-card. For this purpoase, I select one combo card reader: Digifusion SD2 GO 120 in 1:

However, when the Digifusion card reader is connected to the USB port on my MBP, the card reader is automatically mounted by Mac OSX. Of course I can manually add USB filter with VirtualBox GUI

But I don't like GUI that breaks my idea to automate development environment setup. So, I need to automate it with VBoxManage.

First, it's failed to enable virtual USB controller. You need to install VirtualBox 4.2.18 Oracle VM VirtualBox Extension Pack. After installing extension pack, the --usb on and --usbehci on can work successfully with Vagrantfile:

box.vm.provider :virtualbox do |vb|
    vb.customize ["modifyvm", :id, "--usb", "on"]
    vb.customize ["modifyvm", :id, "--usbehci", "on"]

Second, you need to add USB filter with VBoxManage usbfilter command. Before writing the filter, you can observe that Digifusion card reader is treated as mass storage:

$ VBoxManage list usbhost
UUID:               493f68ba-d20c-4830-94dc-db372fdc7236
VendorId:           0x05ac (05AC)
ProductId:          0x8510 (8510)
Revision:           128.37 (12837)
Port:               1
USB version/speed:  0/2
Manufacturer:       Apple Inc.
Product:            FaceTime HD Camera (Built-in)
SerialNumber:       CC2D4K0FFXDN9KE0
Address:            p=0x8510;v=0x05ac;s=0x00000f28d601571d;l=0x1a110000
Current State:      Busy

UUID:               13e7ef3b-e262-48b0-9281-fe8b988d4446
VendorId:           0x14cd (14CD)
ProductId:          0x127a (127A)
Revision:           1.0 (0100)
Port:               1
USB version/speed:  0/2
Manufacturer:       Generic
Product:            Mass Storage Device
SerialNumber:       127A20090522
Address:            p=0x127a;v=0x14cd;s=0x00002a2d9bb767a7;l=0x1d110000
Current State:      Held

So, to solve the problem simply, I add one USB filter to allow VirtualBox to mount any USB mass storage onto the VM:

box.vm.provider :virtualbox do |vb|
    vb.customize ["usbfilter", "add", "0", 
        "--target", :id, 
        "--name", "Any mass storage", 
        "--manufacturer", "Generic",
        "--product", "Mass Storage Device"]

With above script, when the VM is launched with vagrant up command, you can see one USB filter "Any mass storage" is added in VirtualBox GUI:

And, the devices in Ubuntu (precise64) for Digifusion card reader are mounted as sdb ~ sdd:

vagrant@sbc-env:~$ ls -al /dev/sd*
brw-rw---- 1 root disk 8,  0 Oct 13 16:46 /dev/sda
brw-rw---- 1 root disk 8,  1 Oct 13 16:46 /dev/sda1
brw-rw---- 1 root disk 8,  2 Oct 13 16:46 /dev/sda2
brw-rw---- 1 root disk 8,  5 Oct 13 16:46 /dev/sda5
brw------- 1 root root 8, 16 Oct 13 16:47 /dev/sdb
brw------- 1 root root 8, 17 Oct 13 16:47 /dev/sdb1
brw------- 1 root root 8, 18 Oct 13 16:47 /dev/sdb2
brw-rw---- 1 root disk 8, 32 Oct 13 16:47 /dev/sdc
brw-rw---- 1 root disk 8, 48 Oct 13 16:47 /dev/sdd


Just keep a note about the performance comparison of bzip2 v.s. pbzip2. (Not professional and accurate...)

bzip2 is a freely available, patent free (see below), high-quality data compressor.
pbzip2 is a parallel implementation of the bzip2 block-sorting file compressor that uses pthreads and achieves near-linear speedup on SMP machines.

Here are the experiment results:

Time Command
bzip2 256.0s bzip2 -k svndump.txt
pbzip2 with 2 processors 126.4s pbzip2 -k -p2 -9 svndump.txt
pbzip2 with 4 processors 66.5s pbzip2 -k -p4 -9 svndump.txt
pbzip2 with 8 processors 53.9s pbzip2 -k -p8 -9 svndump.txt

It's interesting that using 8 processors cannot double the compression speed of using 4 processors.

Experiment Details

Test Environment
The test machine is 8cores Intel(R) Xeon(R) CPU E5620 @ 2.40GHz with CentOS 5.5.

The file to be compressed is a svn repository dump text file with size ~1.15GB:

1234087701 Oct  1 10:11 svndump.txt


time bzip2 -k svndump.txt

real    4m16.064s
user    4m14.826s
sys 0m1.181s

pbzip2 with 2 processors

time pbzip2 -k -p2 -9 svndump.txt

real    2m6.352s
user    4m11.332s
sys 0m2.256s

pbzip2 with 4 processors

time pbzip2 -k -p4 -9 svndump.txt

real    1m6.548s
user    4m25.353s
sys 0m1.810s

pbzip2 with 8 processors

time pbzip2 -k -p8 -9 it-repos.dump.txt

real    0m53.934s
user    7m5.333s
sys 0m2.034s


To learn how to use node-serialport, I need to prepare an easy-to-verify development environment. So, I select VirtualBox + Vagrant + virtual serial port to setup the development environment. The article is to summarize how I setup step-by-step.

Environment Preparation

Before setup, following softwares need to be installed:

Note, it's very easy to install socat with homebrew:

brew install socat

VirtualBox Setup

I select precise64 as the basebox, and initiate the virtualbox:

vagrant init precise64 http://files.vagrantup.com/precise64.box

Next step is to add following lines into the Vagrantfile file at current path:

config.vm.provider :virtualbox do |vb|
    vb.customize ["modifyvm", :id, "--uart1", "0x3f8", "4"]
    vb.customize ["modifyvm", :id, "--uartmode1", "server", "/tmp/my_tty"]

The 1st line of modifyvm is to enable virtual serial port in virtualbox.
The 2nd line of modifyvm is to connect the virtual serial port to a software pipe on host OS (Mac). In this case, the local domain socket (/tmp/my_tty) is used.

Then, launch the box

touch /tmp/my_tty
vagrant up

Note, the first line is to make sure the socket file already exists before the virtual machine is started. The third line is to login the guest OS for manipulating virtual serial port.

VMWare Fusion Setup

(to-be-complete later...)

Test with SocketServer on Host OS

At the Guest OS (Ubuntu 12.04 64 bits), the virtual serial port can be found at /dev/ttyS0. Then, we use screen tool to manipulate the serial port. Let's open a terminal, name it as T1, and type following command:

vagrant ssh
screen /dev/ttyS0 38400

At the Host OS (Mac OSX), the file for local domain socket connected by virtual serial port is /tmp/my_tty. To monitor the domain socket, socat tool is used. Let's open another terminal, name it as T2, and type following command:

socat /tmp/my_tty tcp-listen:9000 &
telnet localhost 9000

Then, when you type some characters on T1 then T2 shows those characters, and vice versa.

At T1, to exit from screen, please press ctrl-a k to kill it.
At T2, after the telnet process is killed, the socat process is also terminated.

Test with Virtual SerialPort on Host OS

The steps are similar to previous section, but the steps for T2 (2nd terminal) are different. Let's type socat -d -d /tmp/my_tty PTY. It might output following messages on the terminal:

2013/09/14 18:41:27 socat[50862] N opening connection to LEN=17 AF=1 "/tmp/my_tty"
2013/09/14 18:41:27 socat[50862] N successfully connected from local address LEN=16 AF=1 ""
2013/09/14 18:41:27 socat[50862] N successfully connected via
2013/09/14 18:41:27 socat[50862] N PTY is /dev/ttys001
2013/09/14 18:41:27 socat[50862] N starting data transfer loop with FDs [3,3] and [4,4]
2013/09/14 18:42:37 socat[50862] N socket 2 (fd 4) is at EOF
2013/09/14 18:42:37 socat[50862] N socket 1 (fd 3) is at EOF
2013/09/14 18:42:37 socat[50862] N socket 2 (fd 4) is at EOF
2013/09/14 18:42:37 socat[50862] N exiting with status 0

socat indicates the named pipe for virtual serial port on host OS is created, and placed at /dev/ttys001. Then, type screen /dev/ttys001 38400. Finally, the virtual serial ports on both Guest and Host OSes are connected.