NAS Services

Install Samba from apt package manager.

$ sudo apt install samba

A. For restricted access

Add a user for samba. It has nothing to do with existing user on Ubuntu.

$ sudo smbpasswd -a new-user-name

Add a new share for sharing a relevant directory.

$ sudo vi /etc/samba/smb.conf

Paste following into the end of the file. Of course, you can add another share entity referring to format below.

[ODROID NAS]
comment = NAS
path = /media/nas/hdd1
valid users = your-user-name other-name1 other-name2 @your-group-name
writable = yes
create mask = 0775
directory mask = 0775
# Tweaks
write cache size = 524288
getwd cache = yes
use sendfile = yes
min receivefile size = 16384
socket options = TCP_NODELAY IPTOS_LOWDELAY

Test your Samba configuration and restart Samba service.

$ sudo testparm
$ sudo service smbd restart

And you can access Samba from your device.

B. For permitting anonymous access

Create a shared directory and change ownership and permission.

$ sudo mkdir -p /path/to/shared
$ sudo chown -R nobody:nogroup /path/to/shared
$ sudo chmod -R 777 /path/to/shared

And add configuration below to the /etc/samba/smb.conf file.

[ODROID NAS]
comment = NAS
path = /path/to/shared
browseable = yes
guest ok = yes
read only = no
create mask = 0777
# Tweaks
write cache size = 524288
getwd cache = yes
use sendfile = yes
min receivefile size = 16384
socket options = TCP_NODELAY IPTOS_LOWDELAY

Test your Samba configuration and restart Samba service.

$ sudo testparm
$ sudo service smbd restart

And you can access Samba from your device.

1. Install

You should add a unofficial PPA (this is for ARM) on your Ubuntu to download and update Plex Media Server via apt package manager.
This is an official install instruction.

$ wget -O - https://dev2day.de/pms/dev2day-pms.gpg.key | sudo apt-key add -
$ sudo sh -c 'echo "deb https://dev2day.de/pms/ jessie main" >> /etc/apt/sources.list.d/pms.list'
$ sudo apt install apt-transport-https
$ sudo apt update && sudo apt install plexmediaserver-installer

If it installed properly, you can access Plex Media Server by entering URL http://your-odroid-ip:32400/manage into your web browser.

2. Configuration

If you are using it for the first time, sign up first before proceed.

Just follow the instructions on the screen.
In the “Add Library” - “Add Folder” section, the HDD installed in ODROID appears as “/media/nas/hdd1” path. You can set that as the media file path.

It will similar to this screenshot. Installation will be completed when you proceed.

Go to “Settings” - “Transcoder” menu, set “Transcoder quality” to “Prefer higher speed encoding” and then click “SAVE CHANGES” button.
And you can apply any other settings as your taste.

  • It is recommended to disable DLNA feature. Plex one is too heavy to play it with ODROID NAS. Alternatively you can install miniDLNA or Serviio and guide for installing Serviio is provided here.

3. Streaming media

You can start streaming media immediately on your various devices.
The streaming via PC can be done right away at the web page.
And you can do the same thing on the Android and iOS devices after installing Plex application.
Installing the app is free but you will have to pay for it because it will stop the video every minute.

Troubleshooting

  • If you're in trouble with leaking memory when it runs on Kodi - Plex addon, please refer to this thread.
    on the online interface https://app.plex.tv/ -> Settings -> Network
    Secured Connections -> set it back to Disabled
    Check - Enable local network discovery (GDM)
    
    On the Plex addon Settings -> Advanced
    Allow Insecure Connections - On Same Network
    Check - Server Discovery (GDM)
  • You can use DLNA service if you installed the Plex Media Server. But it is recommended to install Serviio when you're watching the high quality videos or it has its subtitles.
  • References

1. Install

  • The version here might be different from real latest version so you would check the latest version yourself.

Enter the following commands to install the necessary packages for Serviio.

  • The Java JDK installation will ask for license agreement. If you don't agree, it will not be installed.
# OMV(Debian)
$ echo "deb http://ppa.launchpad.net/webupd8team/java/ubuntu xenial main" | sudo tee /etc/apt/sources.list.d/webupd8team-java.list
$ echo "deb-src http://ppa.launchpad.net/webupd8team/java/ubuntu xenial main" | sudo tee -a /etc/apt/sources.list.d/webupd8team-java.list
$ sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys EEA14886
$ sudo apt-get update && sudo apt-get install -y ffmpeg dcraw oracle-java8-installer
 
# Ubuntu
$ sudo add-apt-repository ppa:webupd8team/java
$ sudo apt update && sudo apt install -y ffmpeg dcraw oracle-java8-installer

Then proceed with the official installation instruction.

$ sudo useradd -r -s /bin/false serviio
$ sudo mkdir -p /opt
$ cd /opt
$ sudo wget http://download.serviio.org/releases/serviio-1.9-linux.tar.gz
$ sudo tar zxvf serviio-1.9-linux.tar.gz
$ sudo rm serviio-1.9-linux.tar.gz
$ sudo ln -s serviio-1.9 serviio
$ sudo chown -R root:root serviio-1.9
$ cd serviio-1.9
$ sudo mkdir log
$ sudo chown -R serviio:serviio library log

2. Auto start

You should register Serviio as a service so that ODROID-HC1 will start automatically when your ODROID NAS is rebooted.

$ sudo vi /etc/systemd/system/serviio.service

Copy and paste the following:

[Unit]
Description=Serviio Media Server
After=syslog.target local-fs.target network.target
 
[Service]
Type=simple
User=serviio
Group=serviio
ExecStart=/opt/serviio/bin/serviio.sh
ExecStop=/opt/serviio/bin/serviio.sh -stop
KillMode=none
Restart=on-abort
 
[Install]
WantedBy=multi-user.target

And register the new service to the system so that the newly created service works properly.

$ sudo systemctl daemon-reload
$ sudo systemctl enable serviio
$ sudo service serviio start

3. Setup shared media

  • If the console page is not immediately visible, try again in a few minutes.

You can setting up the Serviio through the websites.
Open a web browser and enter http://your-odroid-ip:23423/console into the address bar.

Go to “Library” - “Shared folders” menu.
Click “Add” button to specify the path of media folder which willing to be shared.
As this time, the mounted HDD is named “/media/nas/hdd1”.

Select “Media type” and click “Browse” button to specify the path. If you're done, click “OK” - “Save” button to save.

4. Streaming media

You can start streaming media on your PC, as well as on a variety of devices including smartphones and smart TVs with DLNA support.

1. Install and Configuration

Install Transmission via apt package manager.

$ sudo apt install transmission-daemon

And stop the transmission service to set up.

$ sudo service transmission-daemon stop

Create a directory for Transmission. Of course, written here is an example.

$ sudo mkdir -p /media/nas/hdd1/torrent/complete
$ sudo mkdir -p /media/nas/hdd1/torrent/incomplete

Open transmission settings file and edit entities below.

$ sudo vi /etc/transmission-daemon/settings.json
# "..." means omitted options.
{
    ...
    "download-dir": "/media/nas/hdd1/torrent/complete",
    ...
    "incomplete-dir": "/media/nas/hdd1/torrent/incomplete",
    "incomplete-dir-enabled": true,
    ...
    "rpc-password": "your-password-here",
    ...
    "rpc-username": "your-username-here",
    "rpc-whitelist-enabled": false,
    ...   
}

You have to set the permissions appropriately. If not, it doesn't work.

$ sudo usermod -a -G your-group-name debian-transmission
$ sudo chown -R your-user-name:your-group-name /media/nas/hdd1/torrent
$ sudo chmod -R 775 /media/nas/hdd1/torrent

Also you can set the options as your taste.
Start service again.

$ sudo service transmission-daemon start

2. Access

You can access your Transmission server. Enter http://your-odroid-ip:9091 into the address bar at the top of the web browser.
And login with the account you set.

  • Files uploaded to Seafile are all stored on the server as be split. If you want to get the complete files, refer to the document below.
  • Enable email features so that getting various notification and share your files by sending a email.

1. Install

Download Seafile server for ARM.

$ wget https://github.com/haiwen/seafile-rpi/releases/download/v6.2.5/seafile-server_6.2.5_stable_pi.tar.gz

And since the web service of Seafile works with Nginx, we are going to install the Seafile into the “/var/www” path. Create a directory for Seafile, and deploy for the Seafile directories.

$ sudo mkdir -p /var/www/seafile
$ sudo mv seafile-server_* /var/www/seafile
$ cd /var/www/seafile
$ sudo tar -xzf seafile-server_*
$ sudo mkdir installed
$ sudo mv seafile-server_* installed

Install necessary packages before installing Seafile.

$ sudo apt install python python2.7 libpython2.7 python-setuptools python-imaging python-ldap python-mysqldb python-memcache python-urllib3 python-pip python-dev libmemcached-dev zlib1g-dev python-requests memcached

Enter following commands to install.

$ cd seafile-server-6.2.5
$ sudo ./setup-seafile-mysql.sh

Following text is the example of installation result. Follow the example below and answer the question as you please.
Questions that do not have an answer during the example are questions that use default values via the Enter key.

Checking python on this machine ...
  Checking python module: setuptools ... Done.
  Checking python module: python-imaging ... Done.
  Checking python module: python-mysqldb ... Done.

-----------------------------------------------------------------
This script will guide you to setup your seafile server using MySQL.
Make sure you have read seafile server manual at

        https://github.com/haiwen/seafile/wiki

Press ENTER to continue
-----------------------------------------------------------------


What is the name of the server? It will be displayed on the client.
3 - 15 letters or digits
[ server name ] ODROID

What is the ip or domain of the server?
For example: www.mycompany.com, 192.168.1.101
[ This server's ip or domain ] 192.168.0.2

Where do you want to put your seafile data?
Please use a volume with enough free space
[ default "/var/www/seafile/seafile-data" ] /media/nas/hdd1/seafile-data

Which port do you want to use for the seafile fileserver?
[ default "8082" ] 

-------------------------------------------------------
Please choose a way to initialize seafile databases:
-------------------------------------------------------

[1] Create new ccnet/seafile/seahub databases
[2] Use existing ccnet/seafile/seahub databases

[ 1 or 2 ] 1

What is the host of mysql server?
[ default "localhost" ] 

What is the port of mysql server?
[ default "3306" ] 

What is the password of the mysql root user?
[ root password ] 

verifying password of user root ...  done

Enter the name for mysql user of seafile. It would be created if not exists.
[ default "seafile" ] 

Enter the password for mysql user "seafile":
[ password for seafile ] 

Enter the database name for ccnet-server:
[ default "ccnet-db" ] 

Enter the database name for seafile-server:
[ default "seafile-db" ] 

Enter the database name for seahub:
[ default "seahub-db" ] 

---------------------------------
This is your configuration
---------------------------------

    server name:            Example
    server ip/domain:       192.168.0.2

    seafile data dir:       /media/nas/hdd1/seafile-data
    fileserver port:        8082

    database:               create new
    ccnet database:         ccnet-db
    seafile database:       seafile-db
    seahub database:        seahub-db
    database user:          seafile



---------------------------------
Press ENTER to continue, or Ctrl-C to abort
---------------------------------

Generating ccnet configuration ...

done
Successly create configuration dir /var/www/seafile/ccnet.
Generating seafile configuration ...

Done.
done
Generating seahub configuration ...

----------------------------------------
Now creating seahub database tables ...

----------------------------------------

creating seafile-server-latest symbolic link ...  done




-----------------------------------------------------------------
Your seafile server configuration has been finished successfully.
-----------------------------------------------------------------

run seafile server:     ./seafile.sh { start | stop | restart }
run seahub  server:     ./seahub.sh  { start  | stop | restart  }

-----------------------------------------------------------------
If you are behind a firewall, remember to allow input/output of these tcp ports:
-----------------------------------------------------------------

port of seafile fileserver:   8082
port of seahub:               8000

When problems occur, Refer to

        https://github.com/haiwen/seafile/wiki

for information.

2. Basic configuration

1) Set timezone

If you use it with the default setting, the timezone might be different from actually where you are. You have to manually set the timezone so you can see exactly when you are creating, editing, and deleting the files.
Open seahub_settings file to set the timezone.

$ sudo vi /var/www/seafile/conf/seahub_settings.py

Put below into the end of the file. The “Asia/Seoul” part should be edited as yours.

TIME_ZONE = 'Asia/Seoul'

2) Auto start

Let's setup Seafile to start automatically when your ODROID NAS is booted. Since Seafile is a standalone program(Not a web application), you have to setup this manually.
We are going to create/register a service for Seafile and Seahub.
Create a service for Seafile first.

$ sudo vi /etc/systemd/system/seafile.service

Copy following text and paste it, then save.

[Unit]
Description=Seafile
# add mysql.service or postgresql.service depending on your database to the line below
After=network.target mysql.service
 
[Service]
Type=oneshot
ExecStart=/var/www/seafile/seafile-server-latest/seafile.sh start
ExecStop=/var/www/seafile/seafile-server-latest/seafile.sh stop
RemainAfterExit=yes
User=root
Group=root
 
[Install]
WantedBy=multi-user.target

And create the service for Seahub.

$ sudo vi /etc/systemd/system/seahub.service

Copy following text and paste it, and save.

[Unit]
Description=Seafile hub
After=network.target seafile.service
 
[Service]
# change start to start-fastcgi if you want to run fastcgi
ExecStart=/var/www/seafile/seafile-server-latest/seahub.sh start
ExecStop=/var/www/seafile/seafile-server-latest/seahub.sh stop
User=root
Group=root
Type=oneshot
RemainAfterExit=yes
 
[Install]
WantedBy=multi-user.target

Register the services you created to the system and enable them by enter following commands.

$ sudo systemctl enable seafile.service && sudo systemctl enable seahub.service

3) Performance optimization using Memcache

You can improve the response speed of Seafile by applying Memcache. Since it is supported by default, just enter the setup strings simply.
Install necessary packages via Python package manager.

$ sudo easy_install --upgrade pip
$ sudo -H pip install pylibmc
$ sudo -H pip install django-pylibmc

And put following contents at the end of the seahub_settings.py file.

$ sudo vi /var/www/seafile/conf/seahub_settings.py
CACHES = {
    'default': {
        'BACKEND': 'django_pylibmc.memcached.PyLibMCCache',
        'LOCATION': '127.0.0.1:11211',
    }
}

3. Execute Seafile/Seahub

Seafile runs as a shell script file. Seafile consists of Seafile, a back end part for managing data, and Seahub, a front end part for providing an interface to the user, such as Django, and CCnet for internal RPC that connects the two. So you need to run both Seafile and Seahub to use it.
Even if you register that as a service for automatic start up, Seahub will have to be executed for the first time. This is because you need to create an administrator account.
Execute Seafile and Seahub using following commands.

$ cd /var/www/seafile/seafile-server-latest
$ sudo ./seafile.sh start
$ sudo ./seahub.sh start

The appears message at first runs is:

LC_ALL is not set in ENV, set to en_US.UTF-8
Starting seahub at port 8000 ...

----------------------------------------
It's the first time you start the seafile server. Now let's create the admin account
----------------------------------------

What is the email for the admin account?
[ admin email ] admin@example.com

What is the password for the admin account?
[ admin password ] 

Enter the password again:
[ admin password again ] 



----------------------------------------
Successfully created seafile admin
----------------------------------------




Seahub is started

Done.

If Seafile and Seahub are running normally, you can access Seahub just enter http://your-odroid-ip:8000 into the address bar of the web browser.


4. Install client applications

Seafile provides the clients for various platform. You can refer to following link to get the installation file and to get more information of each client.
https://www.seafile.com/en/download/

  • You can use a embedded WebDAV module on Nginx very easily but it seems to be having some problems.
  • References

Create a directory for WebDAV and change permission and ownership.

# Join www-data into the group for using it from various services such as Samba, Transmission, ...
$ sudo usermod -a -G your-group-name www-data
 
$ sudo mkdir /media/nas/hdd1/webdav
$ sudo chown -R your-user-name:your-group-name /media/nas/hdd1/webdav
$ sudo chmod -R 775 /media/nas/hdd1/webdav

Install pre-required PHP modules.

  • It might be not needed all of the written modules. But Sabre/DAV doesn't specify what modules are required.
$ sudo apt-get install php7.1-gd php7.1-json php7.1-mysql php7.1-curl php7.1-mbstring php7.1-intl php7.1-mcrypt php-imagick php7.1-xml php7.1-zip

Download latest Sabre/DAV from this site into your ODROID NAS using wget command: https://github.com/sabre-io/dav/releases

# The package linked below might be different from yours (out of date). Check the latest version by yourself.
$ wget https://github.com/sabre-io/dav/releases/download/3.2.2/sabredav-3.2.2.zip

Install unzip through apt, and unzip that.

$ sudo unzip -d /var/www sabredav-3.2.2.zip

And prepare to use.

$ sudo mkdir /var/www/SabreDAV/data
$ sudo chmod 777 /var/www/SabreDAV/data

Create a server.php file that will be using as an index file. This file includes how we use the features provided from Sabre/DAV, in PHP language.
In this guide, we use it only as a WebDAV server.

$ sudo vi /var/www/SabreDAV/server.php

Paste following code, it is from the official document http://sabre.io/dav/gettingstarted/.
Take care of the rootDirectory variable. The path it has is the path you want to share using WebDAV so it should be changed to yours.

<?php
use Sabre\DAV;
 
// The autoloader
require 'vendor/autoload.php';
 
// Now we're creating a whole bunch of objects
$rootDirectory = new DAV\FS\Directory('/media/nas/hdd1/webdav');
 
// The server object is responsible for making sense out of the WebDAV protocol
$server = new DAV\Server($rootDirectory);
 
// If your server is not on your webroot, make sure the following line has the
// correct information
$server->setBaseUri('/');
 
// The lock manager is reponsible for making sure users don't overwrite
// each others changes.
$lockBackend = new DAV\Locks\Backend\File('data/locks');
$lockPlugin = new DAV\Locks\Plugin($lockBackend);
$server->addPlugin($lockPlugin);
 
// This ensures that we get a pretty index in the browser, but it is
// optional.
$server->addPlugin(new DAV\Browser\Plugin());
 
// All we need to do now, is to fire up the server
$server->exec();
 
?>

Change the ownership.

$ sudo chown -R www-data:www-data /var/www/SabreDAV

We want to make WebDAV has specific port number like http://your-odroid-ip:8100, so we insert following below into the new server file.
Written paths and port number should be changed to yours.

$ sudo vi /etc/nginx/sites-available/sabredav
server {
    listen 8100;
    listen [::]:8100;
    server_name _;
 
    root /var/www/SabreDAV;
    index server.php;
 
    error_log /var/log/nginx/webdav.error.log;
    access_log /var/log/nginx/webdav.access.log;
 
    charset utf8;
    dav_methods off;
    client_max_body_size 1G;
 
    rewrite ^(.*)$ /server.php break;
 
    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;
    }
}

Enable it and reload Nginx.

$ sudo ln -s /etc/nginx/sites-available/sabredav /etc/nginx/sites-enabled/sabredav
$ sudo service nginx reload

Authenticate

If you want to make it restricted, you can create a account for WebDAV login.
To use htpasswd program, install apache2-utils.

$ sudo apt-get install apache2-utils

And Add a user for WebDAV use.

$ sudo htpasswd -c /etc/nginx/.htpasswd webdav-user-name
# requests
New password: 
Re-type new password: 

Finally add following two lines into the server file, the end of the location / { .. } block.

# Refer to above, if you proceed with method 1...
$ sudo /etc/nginx/sites-available/default
 
# method 2...
$ sudo /etc/nginx/sites-available/webdav
auth_basic              "Prompt message here";
auth_basic_user_file    /etc/nginx/.htpasswd;

Reload Nginx.

$ sudo service nginx reload

If you want to add more user account, enter like following command.

$ sudo htpasswd /etc/nginx/.htpasswd new-user-name
  • Migration from current access address to other address might be difficult. So if you are planning to apply a Domain/SSL for the Wordpress, access/init/posting Wordpress after all of the setup process is done.

1. Prepare database

You have to create a database for Wordpress.

$ sudo mysql -u root -p
> CREATE DATABASE `wordpress-db`;
> CREATE USER 'wordpress'@'localhost' IDENTIFIED BY 'password-here';
> GRANT ALL PRIVILEGES ON `wordpress-db`.* TO 'wordpress'@'localhost' IDENTIFIED BY 'password-here';
> FLUSH PRIVILEGES;

You have created a database named “wordpress-db” and a user named “wordpress”.

2. Install

Download the latest Wordpress installation file.

$ wget https://wordpress.org/latest.zip

Unzip and remove.

$ sudo unzip -d /var/www latest.zip
$ rm latest.zip

And you have to edit the global settings file of Wordpress.

$ cd /var/www/wordpress
$ sudo vi wp-config-sample.php

Find contents below and edit.

...
 
// ** MySQL settings - You can get this info from your web host ** //
/** The name of the database for WordPress */
define('DB_NAME', 'wordpress-db'); // The database name for Wordpress
 
/** MySQL database username */
define('DB_USER', 'wordpress'); // The database user name for Wordpress
 
/** MySQL database password */
define('DB_PASSWORD', 'your-password'); // Password of the user
 
...
 
/**#@+
 * Authentication Unique Keys and Salts.
 *
 * Change these to different unique phrases!
 * You can generate these using the {@link https://api.wordpress.org/secret-key/1.1/salt/ WordPress.org secret-key service}
 * You can change these at any point in time to invalidate all existing cookies. This will force all users to have to log in again.
 *
 * @since 2.6.0
 */
/**
 * Delete all of the contents below and go to the link to replace the contents below.
 * https://api.wordpress.org/secret-key/1.1/salt/
 */
define('AUTH_KEY',         'put your unique phrase here');
define('SECURE_AUTH_KEY',  'put your unique phrase here');
define('LOGGED_IN_KEY',    'put your unique phrase here');
define('NONCE_KEY',        'put your unique phrase here');
define('AUTH_SALT',        'put your unique phrase here');
define('SECURE_AUTH_SALT', 'put your unique phrase here');
define('LOGGED_IN_SALT',   'put your unique phrase here');
define('NONCE_SALT',       'put your unique phrase here');
 
...

Rename the settings file.

$ sudo cp wp-config-sample.php wp-config.php

Create a new shell script file to set the permissions.

$ cd ~
$ vi fix-wordpress-permission.sh

Copy contents below and paste it.

#!/bin/bash
#
# This script configures WordPress file permissions based on recommendations
# from http://codex.wordpress.org/Hardening_WordPress#File_permissions
#
# Author: Michael Conigliaro 
#
WP_OWNER=www-data # <-- wordpress owner
WP_GROUP=www-data # <-- wordpress group
WP_ROOT=$1 # <-- wordpress root directory
WS_GROUP=www-data # <-- webserver group
 
# reset to safe defaults
find ${WP_ROOT} -exec chown ${WP_OWNER}:${WP_GROUP} {} \;
find ${WP_ROOT} -type d -exec chmod 755 {} \;
find ${WP_ROOT} -type f -exec chmod 644 {} \;
 
# allow wordpress to manage wp-config.php (but prevent world access)
chgrp ${WS_GROUP} ${WP_ROOT}/wp-config.php
chmod 660 ${WP_ROOT}/wp-config.php
 
# allow wordpress to manage wp-content
find ${WP_ROOT}/wp-content -exec chgrp ${WS_GROUP} {} \;
find ${WP_ROOT}/wp-content -type d -exec chmod 775 {} \;
find ${WP_ROOT}/wp-content -type f -exec chmod 664 {} \;

After save, grant the permission to execute, and execute it.

$ chmod 755 fix-wordpress-permission.sh
$ sudo ./fix-wordpress-permission.sh /var/www/wordpress
$ rm fix-wordpress-permission.sh

3. Nginx setup

Add a server to Nginx for running Wordpress.

$ sudo vi /etc/nginx/sites-available/wordpress

Paste below. We choose the port 8001 and you can change this number.

server {
        listen 8001;
        listen [::]:8001;
        server_name _;
 
        root /var/www/wordpress;
        index index.html index.php;
 
        error_log /var/log/nginx/wordpress.error.log;
        access_log /var/log/nginx/wordpress.access.log;
 
        charset utf8;
 
        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;
        }
}

Enable that server file and reload Nginx.

$ sudo ln -s /etc/nginx/sites-available/wordpress /etc/nginx/sites-enabled/wordpress
$ sudo service nginx reload

4. Access

You can access your Wordpress websites by URL http://your-odroid-ip:8001/.
Of course you can add a plugin or a theme you want to apply.

  • This guide also can be applied to setup OwnCloud.

1. Prepare database

You have to create a database for NextCloud.

$ sudo mysql -u root -p
> CREATE DATABASE `nextcloud-db`;
> CREATE USER 'nextcloud'@'localhost' IDENTIFIED BY 'password-here';
> GRANT ALL PRIVILEGES ON `nextcloud-db`.* TO 'nextcloud'@'localhost' IDENTIFIED BY 'password-here';
> FLUSH PRIVILEGES;

You have created a database named “nextcloud-db” and a user named “nextcloud”.

2. Install

Install necessary PHP related modules.

$ sudo apt install php7.1-gd php7.1-json php7.1-mysql php7.1-curl php7.1-mbstring php7.1-intl php7.1-mcrypt php-imagick php7.1-xml php7.1-zip php7.1-apcu

Join www-data in the nas group.

$ sudo usermod -a -G your-group-name www-data

Make a directory for NextCloud data and change ownership for it.

$ sudo mkdir /media/nas/hdd1/nextcloud-data
$ sudo chown -R www-data:your-group-name /media/nas/hdd1/nextcloud-data

Download latest NextCloud using wget and decompress it.

$ wget https://download.nextcloud.com/server/releases/nextcloud-12.0.3.tar.bz2
$ tar xvf nextcloud-12.0.3.tar.bz2

Copy it under the /var/www path.

$ sudo cp -r nextcloud /var/www

Change its ownership for Nginx.

$ sudo chown -R www-data:www-data /var/www/nextcloud

Now initialize NextCloud by using occ command as your HTTP user. Note that occ isn't a general linux provided command. NextCloud (forked from OwnCloud) made it.

We had tried initialize it on Web GUI but sometimes some errors occurred, we don't know whether it causes only on our system or not.
Installing from command line seems to be more stable.

You have to move your bash to NextCloud's root directory. And change entered password and HDD's mount point path to yours when you're typing.

$ cd /var/www/nextcloud
$ sudo -u www-data php occ maintenance:install --database "mysql" --database-name "nextcloud-db" --database-user "nextcloud" --database-pass "your-password-here" --admin-user "admin-user-name" --admin-pass "admin-password" --data-dir "/media/nas/hdd1/nextcloud-data"
 
# results
Nextcloud is not installed - only a limited number of commands are available
Nextcloud was successfully installed

Open the config.php file for some setup procedures.

$ sudo vi /var/www/nextcloud/config/config.php

The file may look like below.

First, add memcache module by adding following line.
And second, add ODROID's domain (just IP with port number for now) into the array that has trusted domains.

The line starts with “'memcache.local' ⇒ '/OC/Memcache/APCu',” is the added line for using memcache module.
And the “1 ⇒ 'your-odroid-ip:8002',” entity in the array is the new trusted domain.

<?php
$CONFIG = array (
  ... 
  'trusted_domains' =>
  array (
    0 => 'localhost',
    1 => 'your-odroid-ip:8002',
  ),
  ...
  'memcache.local' => '\OC\Memcache\APCu',
);

We should let PHP-FPM knows the $PATH environment variable. Check the $PATH environment variable.

$ sudo printenv PATH
 
# results
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/bin

Remember that. And open a www.conf file.

$ sudo vi /etc/php/7.1/fpm/pool.d/www.conf

Find out the part about passing the environment variables.
Uncomment them and edit env[PATH] entity with referring the above results.

...
; Pass environment variables like LD_LIBRARY_PATH. All $VARIABLEs are taken from
; the current environment.
; Default Value: clean env
env[HOSTNAME] = $HOSTNAME
env[PATH] = /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/bin
env[TMP] = /tmp
env[TMPDIR] = /tmp
env[TEMP] = /tmp
...

And open a php.ini file.

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

Find out the OPcache related lines below and edit.

opcache.enable=1
opcache.enable_cli=1
opcache.memory_consumption=128
opcache.interned_strings_buffer=8
opcache.max_accelerated_files=10000
opcache.revalidate_freq=1
opcache.save_comments=1

Reload php7.1-fpm service.

$ sudo service php7.1-fpm restart

3. Nginx setup and Access

Create a new Nginx server configuration file.

$ sudo vi /etc/nginx/sites-available/nextcloud

Paste below. Take care of the user-specific values such as webroot path, …

# Reference: https://docs.nextcloud.com/server/12/admin_manual/installation/nginx.html
upstream php-handler {
    server unix:/var/run/php/php7.1-fpm.sock;
}
 
server {
    listen 8002;
    listen [::]:8002;
 
    root /var/www/nextcloud;
 
    server_name _;
 
    # Add headers to serve security related headers
    # Before enabling Strict-Transport-Security headers please read into this
    # topic first.
    # add_header Strict-Transport-Security "max-age=15768000;
    # includeSubDomains; preload;";
    #
    # WARNING: Only add the preload option once you read about
    # the consequences in https://hstspreload.org/. This option
    # will add the domain to a hardcoded list that is shipped
    # in all major browsers and getting removed from this list
    # could take several months.
    add_header X-Content-Type-Options nosniff;
    add_header X-XSS-Protection "1; mode=block";
    add_header X-Robots-Tag none;
    add_header X-Download-Options noopen;
    add_header X-Permitted-Cross-Domain-Policies none; 
 
    location = /robots.txt {
        allow all;
        log_not_found off;
        access_log off;
    }
 
    # The following 2 rules are only needed for the user_webfinger app.
    # Uncomment it if you're planning to use this app.
    #rewrite ^/.well-known/host-meta /public.php?service=host-meta last;
    #rewrite ^/.well-known/host-meta.json /public.php?service=host-meta-json
    # last;
 
    location = /.well-known/carddav {
      return 301 $scheme://$host/remote.php/dav;
    }
    location = /.well-known/caldav {
      return 301 $scheme://$host/remote.php/dav;
    }
 
    # set max upload size
    client_max_body_size 512M;
    fastcgi_buffers 64 4K;
 
    # Enable gzip but do not remove ETag headers
    gzip on;
    gzip_vary on;
    gzip_comp_level 4;
    gzip_min_length 256;
    gzip_proxied expired no-cache no-store private no_last_modified no_etag auth;
    gzip_types application/atom+xml application/javascript application/json application/ld+json application/manifest+json application/rss+xml application/vnd.geo+json application/vnd.ms-fontobject application/x-font-ttf application/x-web-app-manifest+json application/xhtml+xml application/xml font/opentype image/bmp image/svg+xml image/x-icon text/cache-manifest text/css text/plain text/vcard text/vnd.rim.location.xloc text/vtt text/x-component text/x-cross-domain-policy;
 
    # Uncomment if your server is build with the ngx_pagespeed module
    # This module is currently not supported.
    #pagespeed off;
 
    location / {
        rewrite ^ /index.php$uri;
    }
 
    location ~ ^/(?:build|tests|config|lib|3rdparty|templates|data)/ {
        deny all;
    }
    location ~ ^/(?:\.|autotest|occ|issue|indie|db_|console) {
        deny all;
    }
 
    location ~ ^/(?:index|remote|public|cron|core/ajax/update|status|ocs/v[12]|updater/.+|ocs-provider/.+)\.php(?:$|/) {
        fastcgi_split_path_info ^(.+\.php)(/.*)$;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param PATH_INFO $fastcgi_path_info;
        #Avoid sending the security headers twice
        fastcgi_param modHeadersAvailable true;
        fastcgi_param front_controller_active true;
        fastcgi_pass php-handler;
        fastcgi_intercept_errors on;
        fastcgi_request_buffering off;
	fastcgi_read_timeout 300;
 
    }
 
    location ~ ^/(?:updater|ocs-provider)(?:$|/) {
        try_files $uri/ =404;
        index index.php;
    }
 
    # Adding the cache control header for js and css files
    # Make sure it is BELOW the PHP block
    location ~ \.(?:css|js|woff|svg|gif)$ {
        try_files $uri /index.php$uri$is_args$args;
        add_header Cache-Control "public, max-age=15778463";
        # Add headers to serve security related headers (It is intended to
        # have those duplicated to the ones above)
        # Before enabling Strict-Transport-Security headers please read into
        # this topic first.
        # add_header Strict-Transport-Security "max-age=15768000;
        #  includeSubDomains; preload;";
        #
        # WARNING: Only add the preload option once you read about
        # the consequences in https://hstspreload.org/. This option
        # will add the domain to a hardcoded list that is shipped
        # in all major browsers and getting removed from this list
        # could take several months.
        add_header X-Content-Type-Options nosniff;
        add_header X-XSS-Protection "1; mode=block";
        add_header X-Robots-Tag none;
        add_header X-Download-Options noopen;
        add_header X-Permitted-Cross-Domain-Policies none;
        # Optional: Don't log access to assets
        access_log off;
    }
 
    location ~ \.(?:png|html|ttf|ico|jpg|jpeg)$ {
        try_files $uri /index.php$uri$is_args$args;
        # Optional: Don't log access to other assets
        access_log off;
    }
 
}

Enable it and reload Nginx.

$ sudo ln -s /etc/nginx/sites-available/nextcloud /etc/nginx/sites-enabled/nextcloud
$ sudo service nginx reload

Access to your NextCloud service.

Login with your admin account, and check the admin page.


You can check there's no warning message excepts applying HTTPS (SSL), so this means that you've installed NextCloud successfully.

4. Install client applications

NextCloud provides the clients for various platform. You can refer to following link to get the installation file and to get more information of each client.
https://nextcloud.com/install/#install-clients

  • You must take care of the certificates very securely. Anyone who has the certificate can access your internal network without any interrupt.
  • This guide only shows you how to build a simple OpenVPN server with 1194 port. You might do some further setups such as firewall, proper port-forward or rich features of OpenVPN.
  • There're a lot of authorization methods excepts a way of using a certificate. You can googling to find out them.

1. Build a CA (Certificate Authority)

Install OpenVPN and its recommended packages.

$ sudo apt update
$ sudo apt install openvpn easy-rsa

Create a CA directory using make-cadir command since it must not be leaked.

$ make-cadir ~/openvpn-ca
$ cd ~/openvpn-ca

Open vars file to modify default values, which are appearing the information of the server.

$ vi vars

Find out the lines below and edit as yours.

export KEY_COUNTRY="US"
export KEY_PROVINCE="CA"
export KEY_CITY="SanFrancisco"
export KEY_ORG="Fort-Funston"
export KEY_EMAIL="me@myhost.mydomain"
export KEY_OU="MyOrganizationalUnit"
 
export KEY_NAME="server"

It doesn't matter if you don't modify anything, but don't let them empty.

Build CA to create a server key.

$ ln -s openssl-1.0.0.cnf openssl.cnf
$ . ./vars
 
# results
NOTE: If you run ./clean-all, I will be doing a rm -rf on /home/sammy/openvpn-ca/keys
 
$ ./clean-all
$ ./build-ca

Enter “Enter key” to all of the prompt since already we've changed the values using by default.

Create a server key.

$ ./build-key-server server

Enter just “Enter key” and “y” to all of the prompt.
Do not enter for the challenge password.

Create a DH(Diffie-Hellman) key. It might take a few minutes.

$ ./build-dh

Lastly, create a HMAC(Hash-based Message Authentication Code) key.

$ openvpn --genkey --secret keys/ta.key

2. Server configuration

Now we're going to configure OpenVPN server. Move generated keys into the /etc/openvpn directory.

$ cd ~/openvpn-ca/keys
$ sudo cp ca.crt server.crt server.key ta.key dh2048.pem /etc/openvpn

Import a sample server configuration file, and open it to apply some configuration.

$ gunzip -c /usr/share/doc/openvpn/examples/sample-config-files/server.conf.gz | sudo tee /etc/openvpn/server.conf
$ sudo vi /etc/openvpn/server.conf

Follow the comments below.

##### Uncomment #####
proto tcp # comment out udp line.
 
push "redirect-gateway def1 bypass-dhcp"
 
push "dhcp-option DNS 208.67.222.222"
push "dhcp-option DNS 208.67.220.220"
 
tls-auth ta.key 0
 
cipher AES-128-CBC
 
user nobody
group nogroup
 
##### Add following lines into end of the file #####
key-direction 0
auth SHA256
 
##### Performance turning #####
tun-mtu 48000
;fragment 0
mssfix 0
sndbuf 0
rcvbuf 0

3. Server's network setup

There're 2 things to be modified.
First,

$ sudo vi /etc/sysctl.conf
 
# Uncomment following line.
net.ipv4.ip_forward=1
 
$ sudo sysctl -p

And second, just enter the line below.

$ sudo iptables --table nat --append POSTROUTING --out-interface eth0 -j MASQUERADE

And install iptables-persistent package to easier save/restore iptable settings.
Enter “Yes” when it prompts you to save current rules.

$ sudo apt-get install iptables-persistent

Finally, make sure you've set port-forward for 1194 port.

4. Start OpenVPN service

Start OpenVPN service.

$ sudo systemctl start openvpn@server

You can double check the status.

$ sudo systemctl status openvpn@server
 
# results
● openvpn@server.service - OpenVPN connection to server
   Loaded: loaded (/lib/systemd/system/openvpn@.service; enabled; vendor preset: enabled)
   Active: active (running) since Wed 2017-11-01 11:25:52 KST; 1h 6min ago
     Docs: man:openvpn(8)
           https://community.openvpn.net/openvpn/wiki/Openvpn23ManPage
           https://community.openvpn.net/openvpn/wiki/HOWTO
  Process: 680 ExecStart=/usr/sbin/openvpn --daemon ovpn-%i --status /run/openvpn/%i.status 10 --cd /etc/openvpn --script-security 2 --config /etc/openvpn/%i.conf --writepid 
 Main PID: 683 (openvpn)
   CGroup: /system.slice/system-openvpn.slice/openvpn@server.service
           └─683 /usr/sbin/openvpn --daemon ovpn-server --status /run/openvpn/server.status 10 --cd /etc/openvpn --script-security 2 --config /etc/openvpn/server.conf --write
 
Nov 01 11:25:52 odroid-xu4q-main ovpn-server[683]: GID set to nogroup
Nov 01 11:25:52 odroid-xu4q-main ovpn-server[683]: UID set to nobody
Nov 01 11:25:52 odroid-xu4q-main ovpn-server[683]: UDPv4 link local (bound): [undef]
Nov 01 11:25:52 odroid-xu4q-main ovpn-server[683]: UDPv4 link remote: [undef]
Nov 01 11:25:52 odroid-xu4q-main ovpn-server[683]: MULTI: multi_init called, r=256 v=256
Nov 01 11:25:52 odroid-xu4q-main ovpn-server[683]: IFCONFIG POOL: base=10.8.0.4 size=62, ipv6=0
Nov 01 11:25:52 odroid-xu4q-main ovpn-server[683]: IFCONFIG POOL LIST
Nov 01 11:25:52 odroid-xu4q-main ovpn-server[683]: Initialization Sequence Completed
Nov 01 11:25:52 odroid-xu4q-main systemd[1]: Started OpenVPN connection to server.
Nov 01 12:31:55 odroid-xu4q-main systemd[1]: Started OpenVPN connection to server.
 
$ ip addr show tun0
 
# results
3: tun0:  mtu 1500 qdisc pfifo_fast state UNKNOWN group default qlen 100
    link/none 
    inet 10.8.0.1 peer 10.8.0.2/32 scope global tun0
       valid_lft forever preferred_lft forever
    inet6 fe80::6f7b:6f15:f38c:df4/64 scope link flags 800 
       valid_lft forever preferred_lft forever

And enable the service for automatic start when the server turns on.

$ sudo systemctl enable openvpn@server

5. Create a client key

The client key for the users who are going to connect to your OpenVPN server should be created.
Configure environment variables from vars file and create a key.

$ cd ~/openvpn-ca
$ . ./vars
$ ./build-key client1

client1 is just a nickname, it can be edited as the name or nickname the client uses.

6. Create a client certificate

Before proceed, create a directory for managing the client's certificates.
And we'll grant it a proper permission to prevent from accessing of unpermitted users.

$ mkdir -p ~/client-configs/files
$ chmod 700 ~/client-configs/files

Copy the sample client configuration file and open it for some configure.

$ cp /usr/share/doc/openvpn/examples/sample-config-files/client.conf ~/client-configs/base.conf
$ vi ~/client-configs/base.conf

Follow the comments below.

##### Type server's public IP or domain address #####
remote your-public-address-here 1194
 
##### Uncomment #####
proto tcp # comment out udp line.
nobody
nogroup
 
##### Comment out #####
#ca ca.crt
#cert client.crt
#key client.key
 
##### Add following lines into end of the file #####
key-direction 1
cipher AES-128-CBC
auth SHA256
 
##### Performance turning #####
tun-mtu 48000
;fragment 0
mssfix 0
sndbuf 0
rcvbuf 0
 
##### Uncomment only when if the client is on a Linux system, and has /etc/openvpn/update-resolv-conf file. #####
#script-security 2
#up /etc/openvpn/update-resolv-conf
#down /etc/openvpn/update-resolv-conf

Create a script file for creating a certificate.

$ vi ~/client-configs/make_config.sh

Paste following.

#!/bin/bash
 
# First argument: Client identifier
 
KEY_DIR=~/openvpn-ca/keys
OUTPUT_DIR=~/client-configs/files
BASE_CONFIG=~/client-configs/base.conf
 
cat ${BASE_CONFIG} \
    <(echo -e '<ca>') \
    ${KEY_DIR}/ca.crt \
    <(echo -e '</ca>\n<cert>') \
    ${KEY_DIR}/${1}.crt \
    <(echo -e '</cert>\n<key>') \
    ${KEY_DIR}/${1}.key \
    <(echo -e '</key>\n<tls-auth>') \
    ${KEY_DIR}/ta.key \
    <(echo -e '</tls-auth>') \
    > ${OUTPUT_DIR}/${1}.ovpn

Grant it a proper permission for security.

$ chmod 700 ~/client-configs/make_config.sh

Now create a certificate using this script file. Type a client's nickname you've created before as a parameter.

$ ~/client-configs/make_config.sh client1

Once it's done, you can find out the certificates in the following directory.

$ ls ~/client-configs/files
 
# results
client1.ovpn

7. Done

Done. You can access to your OpenVPN server using this created certificate file.

Transfer the certificate to the client system, and use it with OpenVPN client application for your platform.