Build a powerful Web Server

  • Basic Linux knowledge is required.
  • Operation confirmed with testing in our Ubuntu Minimal 16.04.3 LTS on updated 4.9.51-64 kernel.
  • SSD is not essential but it is required when if you want high performance/highly reliable web server
    • … and at least 256GB SSD is recommended to pursue the best performance.

This guide would let you build your web server using an ODROID-XU4/HC1/HC2 with a SSD.
Powerful but low costs web server will be yours through this guide.

Before you proceed, you have to burn our latest Ubuntu Minimal image into your boot media which can be a microSD card or our eMMC.

Go to following link and download the latest Ubuntu Minimal image.
Ubuntu Minimal 16.04.3 LTS
Go to following link and download etcher for your platform.

Insert your microSD card (or a eMMC with a reader module) to your computer, and run etcher, then burn it into your microSD (or a eMMC).

  • TIP: If you use ODROID-XU4, you can build high performance NAS using a powered USB hub (one SSD/eMMC for OS, one or more HDD for NAS).
    • Actually, buying a powered USB hub is highly recommended for ODROID-XU4 due to the power supply matters.

Install SSD on your ODROID-XU4/HC1/HC2. Make sure enough power is supplied to your SSD.
If you done, insert prepared boot disk into your ODROID and plug the power.

At first boot time, it will takes 5 minutes or above for initializing OS so you should wait or just take some coffee during that time.
In HC1/HC2, it might doesn't turn on after 5 minutes, you can boot again by re-plugging the power cord.

You should connect to your ODROID via SSH and you can build your web server.
And update your ODROID is highly recommended for reliability of the system. Besides Ubuntu, we have been continually developing, updating kernel for letting users to take stable, powerful device.

After SSH access, update Ubuntu and kernel through following commands.

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

In ODROID-HC1, eMMC module cannot be installed to it even though MicroSD card is too slow to handle MySQL database to give static/dynamic web pages to the users.
So install a SSD is highly recommended for hosting websites using database. But in ODROID-XU4, using an eMMC can be chosen rather than installing a SSD.

Follow the step by step guide below to make your SSD as a root partition.

First, you should partitioning again your SSD to use two partitions which are one for a root, and the other for a data.
Check if which device is your SSD and partitioning it using 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 re-partitioning, use fdisk tool with entering proper device name. In shown above, /dev/sda is the SSD.

$ sudo fdisk /dev/sda

And for using fdisk, you should know basic commands 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 emptry GPT partition table
  • m : help (menu)

With referring to the menu above, delete current partitions and create a new GPT partition table, then create a new partition for a root partition, then create another new partition for a data.
Ours root partition has a capacity of 16G and the rest is a data partition.
You can specify the capacity of the partition with typing a capacity unit, for example, “+16G”.

Check your work as see the partition table (enter “p”). And if there's nothing to wrong, enter “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

Modern Linux system is very familiar with an EXT4 file system. So you should make your partitions as an EXT4.
Enter following commands.

$ 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

And you can check if it is mounted properly.

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

At last, modify your system related files to boot with your SSD.

1) /media/boot/boot.ini

First, let's check what is the partition's UUID which will be a root partition.

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

Remember the UUID for /media/systemdrive.
And change root file system's target UUID at boot.ini so that your bootloader recognizes 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 “Basic Ubuntu Setup.”, then it results:

# 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 root=UUID=e139ce78… to the /media/systemdrive's UUID that we checked before.
The UUIDs wrote here might be different from yours.

2) /etc/fstab

Add new lines into /etc/fstab so that makes your drive's partition mounted automatically.

$ sudo vi /etc/fstab
# results
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.
And, it will appears to be like 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

3) Copy a root partition

And copy the root partition using rsync.
Enter following commands.

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

After few minutes, you are ready.

Reboot your ODROID and check if the mounted root partition is in your SSD.

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

As you can see shown above, sda1's MOUNTPOINT is “/”. It means you did boot from SSD successfully.

  • We choose Nginx for the web server. Since Nginx uses an asynchronous, event‑driven approach to handling connections, it can be fast and has room for admitting the many users (above 10K) with keeping stable performance and reliability. And Nginx designed to be lightweight software which consumes less memory and let you escape from setting the complicate options. But, if you want a tons of detailed modules and supports from the huge community, Apache can be your choice.


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. It may be commented out by default.


Official(or any) PPA for MariaDB based on ARM architecture is not available for now. You should just install it from the repository which is provided from Ubuntu. Their MariaDB packages will be slowly updated.
Additionally, you should install php-mysql package to interlock your MariaDB and PHP.

$ 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 the existing contents, and copy-paste a new contents below.

# MariaDB-specific config file.
# Read by /etc/mysql/my.cnf
# Default is Latin1, if you need UTF-8 set this (also in server section)
default-character-set = utf8mb4
# * 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

And restart MariaDB service.

$ sudo service mysql restart


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

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

And if you want to use it with PHP, 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;

And reload Nginx service.

$ sudo service nginx reload

You can test whether it is operated properly or not by creating simple PHP information page.

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

And when you access to http://{ODROID IP}/, then it shows you the information of PHP related things on your system.

  • Environments (Versions)
    • LEMP
      • 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

We used the tools below with test conditions to test its performance.

  • Apache JMeter

  • sysbench
# For MySQL(MariaDB). Before you do, make sure that you have created the 'test' database.
$ 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
# For File IO
$ 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
  • iozone
$ sudo iozone -e -I -a -s 100M -r 4k -r 16384k -i 0 -i 1 -i 2
  • Note that eMMC tests with XU4 and the rest tests with HC1.
  • All the results have its own error range.
  • Since Wordpress runs in PHP, MariaDB(MySQL) and Nginx(Apache), we installed Wordpress at each system to create natural test conditions before JMeter testing, and it accesses to Wordpress's default main page.
  • We realized that response failed if more than 140 parallel users entered (Simple Wordpress's default main 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
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 isn't more faster than even if it uses a MicroSD card in the results of random access speed. The result of OLTP TPS and sequence access speed are quite good but random access speed isn't acceptable. The average TPS shown above is just a average value, and you need to know that random access speed is one of the most important value for the overall system speed. Above all, the OLTP results of the HDD ODROID was continually changed a lot at each test. But as you can see the result of sequence access speed, it is quite as fast as on a desktop so using a HDD for a NAS can be a good choice.

In 100 parallel users TPS, there's nothing much different among them. But in the other things such as OLTP TPS and IOzone test, SSD or eMMC 64G seems faster than the others.

It doesn't included at the result table above, in the file IO test, SSD is the fastest at per-request statistics result.

So it is not recommended that using a HDD or MicroSD card as your root partition when you're hosting a website which consists of LEMP(APM) stack.
We recommend that using an eMMC or SSD for the best performance with an ODROID-XU4/HC1/HC2 when you're hosting a website (and/or using it as a NAS).

  • odroid-xu4/software/building_webserver.txt
  • Last modified: 2022/04/20 16:12
  • by justin