LEMP stack web server: Linux, NGINX, MariaDB, and PHP on the ODROID-HC1

LEMP stack web server: Linux, NGINX, MariaDB, and PHP on the ODROID-HC1

This guide will let you build an inexpensive but powerful web server using an ODROID-HC1 (XU4 family, including the ODROD-HC2) fitted with a SATA-based SSD.

Prepare boot media
Before you proceed to build the web server, burn the latest official Hardkernel Ubuntu Minimal image onto your boot media – 8GB+ Class 10 microSD card. A Hardkernel offered eMMC may also be used, in conjunction with a USB3 microSD card reader.

Go to the http://bit.ly/2xaucO8 link and download the latest Ubuntu Minimal image. Also, access the https://etcher.io/ link and download the appropriate version of Etcher for your operating system. Insert your microSD card in your computer and run Etcher, then burn the image onto your microSD.

Set up your ODROID
Install the SSD using the SATA port on your ODROID-HC1. Make sure you use the official 5V 4A+ Hardkernel PSU, to ensure the SSD has adequate power. Once this is done, insert the prepared boot disk into your ODROID and turn on the power to the ODROID-HC1.

The first boot can take about 5 minutes to initialize the OS. If it does not turn on after about 5 minutes, you can reboot it by turning the power off, disconnecting the power cord, re-plugging the power cord and turning the power back on.

Note that if you use an ODROID-XU4, you can build a high performance NAS using a powered USB hub, one SSD/eMMC for the operating system, and one or more hard drives for the NAS. Bus-powered hubs may not work well, due to inadequate power.

SSH Access and system update
Connect to your ODROID-HC1 via SSH and build your web server. It is highly recommended to update the image on the microSD card. That will let you take advantage of the latest fixes and possible support for additional features. After SSH access, update Ubuntu and the kernel with the following commands:

$ sudo apt-get update && sudo apt-get dist-upgrade
$ sudo apt-get install linux-image-xu3
$ reboot

Make your SSD a root partition
Boot media such as the microSD card makes for an inefficient system because the microSD card will be slow (for the OS and applications running on it, such as the web server) and subject to early failure after excessive writes. Although an eMMC is a viable option for an ODROID-XU4, it is not available for the ODROID-HC1. Therefore, the installation and use of an SSD is highly recommended for hosting websites using databases. To efficiently use the SSD for boot up and applications, follow the step by step guide below to prepare your SSD with a root partition. You can refer to the forum post at http://bit.ly/2gpT9OR for additional details.

Re-partition your SSD
First, you should partition your SSD to use two partitions: one as the root partition for the OS, and the other for data. Obtain information on your SSD using the fdisk tool:

$ sudo fdisk -l
# results
...
Disk /dev/sda: 111.8 GiB, 120034123776 bytes, 234441648 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 4096 bytes
I/O size (minimum/optimal): 4096 bytes / 33553920 bytes
Disklabel type: gpt
Disk identifier: 0412F7EC-4E8C-4610-ABFF-D6293387ADB6

To partition the SSD, use the fdisk tool with entering proper device name (/dev/sda as noted in the output earlier):

$ sudo fdisk /dev/sda

The useful fdisk-options are listed below:

  • p : print the partition table
  • n : add a new partition
  • d : delete a partition
  • w : write table to disk and exit
  • q : quit without saving changes
  • g : create a new empty GPT partition table
  • m : help (menu)

While referring to the menu above, delete current partitions, if any, and create a new GPT partition table. Then create one new partition for a root partition, and another new partition for a data. In our case, the root partition has a capacity of 16G and the rest is a data partition. You can specify the capacity of the partition by typing a capacity unit, for example, “+16G”.

Check the result of your actions by obtaining partition using the “p” option. If the partition information match your intentions, then press “w” to save and exit.

# In fdisk
Command (m for help): p
Disk /dev/sda: 111.8 GiB, 120034123776 bytes, 234441648 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 4096 bytes
I/O size (minimum/optimal): 4096 bytes / 33553920 bytes
Disklabel type: gpt
Disk identifier: 0412F7EC-4E8C-4610-ABFF-D6293387ADB6
 
Device        Start       End   Sectors  Size Type
/dev/sda1      2048  33556479  33554432   16G Linux filesystem
/dev/sda2  33556480 234441614 200885135 95.8G Linux filesystem

Format and mount as an EXT4 partition
A modern Linux system typically uses an EXT4 file system, so it is advisable to create ext4 type partitions:

$ sudo mkfs.ext4 /dev/sda1
$ sudo mkfs.ext4 /dev/sda2

Once you done, you should mount it to specific directory to use your SSD. Make new directories for your SSD:

$ sudo mkdir -p /media/systemdrive
$ sudo mkdir -p /media/data

We will use /media/systemdrive as a root partition, and /media/data as a data partition:

$ sudo mount /dev/sda1 /media/systemdrive
$ sudo mount /dev/sda2 /media/data

Next, verify that it is mounted properly:

$ df -h
Filesystem      Size  Used Avail Use% Mounted on
...
/dev/sda1        16G   44M   15G   1% /media/systemdrive
/dev/sda2        95G   60M   90G   1% /media/data

The next step is to modify your system related files to boot with your SSD.

Modifying boot.ini
First, check the UUID of the root:

$ sudo lsblk -f
# results
NAME        FSTYPE LABEL  UUID                                 MOUNTPOINT
mmcblk1                                                        
|-mmcblk1p1 vfat   boot   52AA-6867                            /media/boot
`-mmcblk1p2 ext4   rootfs e139ce78-9841-40fe-8823-96a304a09859 /
sda                                                            
|-sda2      ext4          6553d8f1-6224-450f-aec1-3b6f5fc09bd0 /media/data
`-sda1      ext4          f00945e6-46ea-47db-893a-6a74548c3af7 /media/systemdrive

Note down the UUID for /media/systemdrive, then change the UUID of the root file system in boot.ini so that your bootloader recognizes the SSD’s partition as a root partition:

$ sudo cp /media/boot/boot.ini /media/boot/boot.ini.bak
$ sudo vi /media/boot/boot.ini

Search for the phrase “Basic Ubuntu Setup” in the file:

...
# Basic Ubuntu Setup. Don't touch unless you know what you are doing.
# --------------------------------
setenv bootrootfs "console=tty1 console=ttySAC2,115200n8 root=UUID=e139ce78-9841-40fe-8823-96a304a09859 rootwait ro fsck.repair=yes net.ifnames=0"
…

Change the root UUID to match the above value. Note that your UUID values may be different from what is mentioned here.

Updating fstab
To mount your partitions automatically, add needed entries in the /etc/fstab file.

$ sudo vi /etc/fstab
UUID=e139ce78-9841-40fe-8823-96a304a09859 / ext4 errors=remount-ro,noatime 0 1
LABEL=boot /media/boot vfat defaults 0 1

Comment out the first line and add new lines, as shown below:

#UUID=e139ce78-9841-40fe-8823-96a304a09859 / ext4 errors=remount-ro,noatime 0 1
LABEL=boot /media/boot vfat defaults 0 1
/dev/sda1 / ext4 defaults,noatime 0 1
/dev/sda2 /media/data ext4 defaults 0 2

Copy a root partition
Copy the root partition from microSD to the SSD using the rsync utility:

$ sudo apt-get install rsync
$ sudo rsync -axv / /media/systemdrive

After the copy process has completed, you are ready for the next step.

Verify the partitions
Reboot your ODROID-HC1 and check if the mounted root partition is visible in your SSD:

$ lsblk -f
NAME        FSTYPE LABEL  UUID                                 MOUNTPOINT
mmcblk1                                                        
|-mmcblk1p1 vfat   boot   52AA-6867                            /media/boot
`-mmcblk1p2 ext4   rootfs e139ce78-9841-40fe-8823-96a304a09859 
sda                                                            
|-sda2      ext4          daff1faa-3895-46cb-896f-bfe67f78535e /media/data
`-sda1      ext4          07ac0233-7d4a-49ac-baf0-4a4ebd07741c /

As shown above, sda1’s MOUNTPOINT is “/”, which means that the system booted from SSD successfully.

LEMP (Linux, NGINX, MariaDB, PHP) stack
We have opted to use nginx for the web server. It uses an asynchronous, event‑driven approach to handling connections, which is fast and has room for serving requests from many users, as well as offering reliable performance. It has been designed to be lightweight software that offers many features. If you wish to avail use features as addon modules, Apache would be a better choice.

PHP
To install PHP, you should add a repository for PHP in advance. And you can install latest PHP for ARM, version 7.1 or above.

$ sudo add-apt-repository ppa:ondrej/php
$ sudo apt-get update && sudo apt-get install php7.1-fpm

Once the installation is done, you should change timezone specified in a setting file of PHP.

$ sudo vi /etc/php/7.1/fpm/php.ini

Find “date.timezone” and change it to your location, which may be initially commented out by default.

MariaDB
An official PPA for MariaDB (http://bit.ly/2zktcMs) based on ARM architecture is not available. You should just install it from the repository which is provided from Ubuntu. Additionally, you should install php-mysql package to interlock your MariaDB and PHP. The installation of the needed packages could take a little while.

$ sudo apt-get update && sudo apt-get install mariadb-server mariadb-client php-mysql

You should set the language set MariaDB uses to UTF-8.

$ sudo vi /etc/mysql/conf.d/mysql.cnf

Delete all of the existing content, and copy-paste a new contents below.

# MariaDB-specific config file.
# Read by /etc/mysql/my.cnf
 
[client]
# Default is Latin1, if you need UTF-8 set this 
# (also in server section)
default-character-set = utf8mb4
 
[mysqld]
#
# * Character sets
#
# Default is Latin1, if you need UTF-8 set all this 
# (also in client section)
#
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci
character_set_server = utf8mb4
collation_server = utf8mb4_unicode_ci

Finally, restart MariaDB service.

$ sudo service mysql restart

Installing nginx
To install nginx, you should add a repository for nginx in advance. You can install the latest version for ARM (version 1.12+):

$ sudo add-apt-repository ppa:nginx/stable
$ sudo apt-get update && sudo apt-get install nginx

If you want to use it with PHP, the server settings must be modified:

$ sudo mv /etc/nginx/sites-available/default /etc/nginx/sites-available/default.bak
$ sudo vi /etc/nginx/sites-available/default

Put below into the new default server file.

server {
	listen 80 default_server;
	listen [::]:80 default_server;
 
	root /var/www/html;
 
	index index.html index.php;
 
	server_name _;
 
	location / {
		try_files $uri $uri/ =404;
	}
 
        # This option is important for using PHP.
	location ~ \.php$ {
		include snippets/fastcgi-php.conf;
		fastcgi_pass unix:/var/run/php/php7.1-fpm.sock;
	}
}

Restart the nginx service:

$ sudo service nginx reload

Testing
You can test whether the web server is operating properly by creating simple PHP information page:

$ echo "?php phpinfo();" | sudo tee /var/www/html/index.php

When you access http://{ODROID IP}/, it will show you PHP related information.
The test conditions include:

  • LEMP stack
    • Ubuntu Minimal 16.04.3 LTS with Kernel 4.9.51-64
    • Nginx 1.12.1
    • PHP 7.1.9
    • MariaDB 10.0.31
    • Benchmark tools
  • Apache JMeter 3.2 r1790748
  • sysbench 0.4.12
  • IOzone 3.471

To test its performance, we ran the tests shown below under the test conditions listed above.

Figure 1 – LEMP performance using Apache JMeter

Sysbench
Create the ‘test’ database first and then run the performance test.

$ sudo sysbench --test=oltp --oltp-table-size=1000000 --mysql-db=test --mysql-user=root prepare
$ sudo sysbench --test=oltp --oltp-table-size=1000000 --mysql-db=test --mysql-user=root --max-time=60 --oltp-read-only=on --max-requests=0 --num-threads=8 run
$ sudo sysbench --test=oltp --mysql-db=test --mysql-user=root cleanup

To test file I/O, run the following test:

$ sudo sysbench --test=fileio --file-total-size=4G prepare
$ sudo sysbench --test=fileio --file-total-size=4G --file-test-mode=rndrw --init-rng=on --max-time=300 --max-requests=0 --num-threads=8 run
$ sudo sysbench --test=fileio --file-total-size=4G cleanup
$ sudo iozone -e -I -a -s 100M -r 4k -r 16384k -i 0 -i 1 -i 2

Results

  • Note that eMMC tests were run on the ODROID-XU4 and the remaining tests were performed on the ODROID-HC1
  • All results have their own error ranges
  • Since WordPress runs using PHP, MariaDB (MySQL) and Nginx (Apache), we installed WordPress at each system to create natural test conditions. JMeter tests were run accessing WordPress’s default main page
  • We noticed that the response failed if more than 140 parallel users accessed the simple WordPress-based web-page)
  • TPS is abbreviation for Transaction Per Second, so this is the closest test to the user’s environment.
HDD 2TB SSD 120G eMMC 64G eMMC 16G MicroSD 8G
Apache JMeter
100 Parallel Users Avg TPS 51.1 53.1 54.5 53.4 52.3
100 Parallel Users Avg Res Time (ms) 1578 1519 1477 1510 1540
sysbench
OLTP(MySQL) Avg TPS 361.81 401.59 396.43 395.14 340.05
FileIO Avg Transfer Speed (Mbps) 1.9359 17.982 24.593 16.738 0.094831
IOzone (Kbps)
Random Read Speed (4K) 1580 20937 15466 15203 9139
Random Write Speed (4K) 1275 21078 15803 17939 827
Sequence Read Speed (16M) 115209 363269 142535 147790 42885
Sequence Write Speed (16M) 108979 278223 88529 33709 13022

As you can see the table above, a HDD is slightly more faster than a MicroSD card for random access speed. The result of OLTP TPS and sequence access speed are quite good, but random access speed is not acceptable. The average TPS shown above is just an average value, and you need to know that random access speed is one of the most important value for the overall system speed. The OLTP results of the HDD ODROID varied a lot between tests. However, for sequence access speed, it is almost as fast as a desktop. So, using an HDD in the ODROID-HC1 for a NAS can be a good choice.

In the 100 parallel users TPS test, there is not much of a difference among them. However, in the other tests such as, the OLTP TPS and IOzone test, the SSD or eMMC 64G seems faster than the others. In the file IO test, the SSD is the fastest at per-request statistics result.

Based on above results, it is not recommended that an HDD or MicroSD card be used with a LEMP or LAMP stack. We recommend that you use an eMMC or SSD for the best performance with an ODROID-XU4/HC1/HC2 when you are hosting a website and/or using it as a NAS. For additional details, please visit the original article at http://bit.ly/2l5aUs1.

Be the first to comment

Leave a Reply