Install nextcloud on Ubuntu server 16.4 with Let’s Encrypt

One of my goals during this project was to regain control of my data which had previously been stored using cloud services like Microsoft’s OneDrive. However, I wanted to host these files myself and be able to access those files remotely.

Now there are two applications that are available, these being OwnCloud and NextCloud both are available for free but NextCloud is a fork of OneCloud (built by the same team) and truly open source which fits into the whole ethos of my project brief, so, for the purposes of this tutorial, I will talk you through installing NextCloud with SSL on an Ubuntu server Virtual Machine on FreeNAS. 

I will assume that you have already installed Ubuntu server on a FreeNAS VM which you are able to access via, SSH.  The text editor that I am going to use throughout this tutorial will be nano (basically because it’s easy to use). If you haven’t used nano before then visit https://www.nano-editor.org/dist/v2.2/nano.html

Create a static IP address

You will need to reserve the IP address of your Ubuntu server on your router, however, I had run into problems with my router so I tend to make the IP static from within Ubuntu and port forward on the router.  If you would like to learn how to do this then please follow the guide on how to set-up a static IP on Ubuntu 16.4

If you are planning on installing NextCloud on Ubuntu Server  17.10 then please follow this guide as the way that network configuration is done is completely different, so, If you are planning on installing on Ubuntu Server 17.10 then please follow this guide on how to setup a static IP on Ubuntu 17.10

Register for & install a no-ip dynamic update client

If you are going to access your NextCloud server from the internet then you will need to make your Ubuntu VM visible from the internet. In this instance, I am going to use a free dynamic DNS from no-ip.com

You can sign up for a free plan to test your setup and if you are happy with it you could go for a paid plan which costs around £20 per year. The free plan gives you three hostnames however you have to confirm that the hostname is active every 30 days. The paid plan gives you 25 hostnames which do not require confirmation every 30 days.

There is a good reason why I am mentioning dynamic DNS at this point in the tutorial and that is because I am going to show you how to implement SSL using Let’s Encrypt. One of the prerequisites before configuring Let’s Encrypt is that you have to have a hostname that can be validated before the security certificate can be issued and installed on the server. As part of the dynamic DNS setup, you get to choose your own hostname which enables you to facilitate the installation of the security certificates.

Login as root

You will need to be logged in as the root user so to assuming that you are already logged in via terminal. To switch to the root account use the following command.

sudo -s

You will be prompted for the administrative password enter it and hit return.

Install make, gcc and zip

Before we start, we will need to install some compilers and a zip utility. This can be done in one go with the following command.

apt install make gcc zip

Once installed, change the directory to /usr/local/src. This isdone with the following command.

cd /usr/local/src

Download the client with.

wget http://www.no-ip.com/client/linux/noip-duc-linux.tar.gz

Once downloaded, unzip the file with

tar xzf noip-duc-linux.tar.gz

Check the version number of the update client. This can be done by looking at the directory in which it resides by using the following command.

ls

Which is basically going to list the contents of the directory you should see something like this in the directory

Change the directory to

cd noip-2.1.9-1

And then use the following commands to compile the client.

make

Followed by.

make install

Which will now configure the client. At this point, you will be asked for your login details and details of the hostname that you created when you registered with No-IP. Once you have answered all the questions the configuration script will be set up.

The last thing to do at this point will be to set up a script to run the No-IP client automatically if the server is restarted for any reason. To create this script run the following commands.

 touch /etc/init.d/noip2
 chmod 755 /etc/init.d/noip2
 update-rc.d noip2 defaults

Then using the following command.

nano /etc/init.d/noip2

Copy and paste this script into the file.

#################################################
#! /bin/sh
#. /etc/rc.d/init.d/functions # uncomment/modify for your killproc
case "$1" in
start)
echo "Starting noip2."
/usr/local/bin/noip2
;;
stop)
echo -n "Shutting down noip2."
killproc -TERM /usr/local/bin/noip2
;;
*)
echo "Usage: $0 {start|stop}"
exit 1
esac
exit 0
#################################################

Save the file with CTRL and X. Restart your VM and the script will now be running.

Install Apache Server

To install Apache server, run the following commands.

apt install apache2

For added security, you will want to disable directory listing. This can be done with the following command.

sed -i "s/Options Indexes FollowSymLinks/Options FollowSymLinks/" /etc/apache2/apache2.conf

Start the server with.

systemctl start apache2.service

You can also use the following commands to stop and restart and enable the server.

systemctl stop apache2.service
systemctl restart apache2.service
systemctl enable apache2.service

Install MariaDB

You can use another database such as MySQL or Postgresql but in this instance, I am going to install MariaDB using the following command.

apt-get install mariadb-server mariadb-client

Once installed you can should start the server with.

systemctl start mysql.service

You will note that this command is the same as the commands we could use to enable, start, restart and stop apache server, all you need to do is replace apache with mysql. Now you have to secure the database installation with the following command.

mysql_secure_installation

When prompted, answer the following questions.

  • Enter current password for root (enter for none): As this is a new installation, no
  • password will have been set so just press the Enter.
  • Set root password? [Y/n]: Y
  • New password: Enter password
  • Re-enter new password: Repeat password
  • Remove anonymous users? [Y/n]: Y
  • Disallow root login remotely? [Y/n]: Y
  • Remove test database and access to it? [Y/n]:  Y
  • Reload privilege tables now? [Y/n]:  Y

Restart MariaDB with.

systemctl restart mysql.service

Create the nextcloud database

Now that MariahDB has bee installed you can now go ahead and create the database that will be used by nextcloud. To do this need to login to MariaDB as root using the password you just created with the following command.

sudo mysql -u root -p

First you will need to create the database.

CREATE DATABASE nextcloud;

Now create a user for the database.

CREATE USER 'nextcloud_admin'@'localhost' IDENTIFIED BY 'new_password_here';

Create the permissions for the nextcloud_admin user with.

GRANT ALL ON nextcloud.* TO 'nextcloud_admin'@'localhost';

Flush all previous privileges with.

FLUSH PRIVILEGES;

Followed by.

EXIT;

Install PHP and related modules

Now the database has been created you can no go on to install PHP. In this instance I would suggest using PHP7.1 By default PHP7.1 is not available through the default Ubuntu repositories, therefore, you will need to add the repository with the following commands.

apt-get install software-properties-common
add-apt-repository ppa:ondrej/php

Then run the following commands to update and upgrade Ubuntu to use PHP7.1

apt update

You can now go ahead and install PHP7.1 with the following command.

sudo apt install php7.1 libapache2-mod-php7.1 php7.1-common libapache2-mod-php7.1 php7.1-mbstring php7.1-xmlrpc php7.1-soap php7.1-apcu php7.1-smbclient php7.1-ldap php7.1-redis php7.1-gd php7.1-xml php7.1-intl php7.1-json php7.1-imagick php7.1-mysql php7.1-cli php7.1-mcrypt php7.1-ldap php7.1-zip php7.1-curl

After PHP7.1 has been installed, run the following command to edit the php.ini file.

nano /etc/php/7.1/apache2/php.ini

Then make changes to the following lines.

file_uploads = On
allow_url_fopen = On
memory_limit = 256M
upload_max_filesize = 64M
max_execution_time = 360
date.timezone = Europe/London

On the line that says date.timezone enter your timezone. For reference, and to get the correct timezone go to http://php.net/manual/en/timezones.php

Finally, save the php.ini file with ctrl and x

Download nextcloud

Use the following command to download the latest version of nextcloud.

cd /tmp && wget https://download.nextcloud.com/server/releases/nextcloud-13.0.1.zip
unzip nextcloud-13.0.1.zip
mv nextcloud /var/www/html/nextcloud/

Set the permissions for NextCloud to run correctly on the server.

chown -R www-data:www-data /var/www/html/nextcloud/
chmod -R 755 /var/www/html/nextcloud/

Configure Apache server

The final stage of the installation will be to configure apache server to server the NextCloud application.  To do this you will need to create a configuration file which will control how users will access NextCloud. Run the following command to create the nextcloud.config file.

nano /etc/apache2/sites-available/nextcloud.conf

Now copy and paste the content below into the file and save it. Replace the highlighted line with your own domain name and directory root location.

<VirtualHost *:80>
ServerAdmin admin@example.com
DocumentRoot /var/www/html/nextcloud/
ServerName example.com
ServerAlias www.example.com

Alias /nextcloud "/var/www/html/nextcloud/"

<Directory /var/www/html/nextcloud/>
Options +FollowSymlinks
AllowOverride All
Require all granted
<IfModule mod_dav.c>
Dav off
</IfModule>
SetEnv HOME /var/www/html/nextcloud
SetEnv HTTP_HOME /var/www/html/nextcloud
</Directory>

ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined

</VirtualHost>

Save the file with ctrl & x

Enable the nextcloud and rewrite modules

Enable the modules with the following commands

a2ensite nextcloud.conf
a2enmod rewrite
a2enmod headers
a2enmod env
a2enmod dir
a2enmod mime

Restart Apache with.

systemctl restart apache2.service

That’s nextcloud installed and configured. You could run the server “as-is” however you will be connecting to it over an insecure connection which is not good especially if you have followed this tutorial and made the server accessible from the outside world.

Download and configure Let’s Encrypt certificates

The Certbot team maintains a PPA. Once you add it to your list of repositories all you’ll need to do is apt-get the following packages.

apt-get update
apt-get install software-properties-common
add-apt-repository ppa:certbot/certbot
apt-get update
apt-get install python-certbot-apache

Once installed, run the commands below to obtain the certificate. Replace the highlighted text with your email and hostname.

certbot --apache -m admin@example.com -d www.example.com

you should be prompted to accept the license agreement.

Please read the Terms of Service at
https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf. You must
agree in order to register with the ACME server at
https://acme-v01.api.letsencrypt.org/directory
-------------------------------------------------------------------------------
(A)gree/(C)ancel: A

It’s up to yourself if you wish to share your email address.

Would you be willing to share your email address with the Electronic Frontier
Foundation, a founding partner of the Let's Encrypt project and the non-profit
organization that develops Certbot? We'd like to send you email about EFF and
our work to encrypt the web, protect its users and defend digital rights.
(Y)es/(N)o:

You will then be asked if you wish to redirect all HTTP traffic to HTTPS. In this instance we do want to redirect all traffic to HTTPS.

Please choose whether or not to redirect HTTP traffic to HTTPS, removing HTTP access.
-------------------------------------------------------------------------------
1: No redirect - Make no further changes to the webserver configuration.
2: Redirect - Make all requests redirect to secure HTTPS access. Choose this for
new sites, or if you're confident your site works on HTTPS. You can undo this
change by editing your web server's configuration.
-------------------------------------------------------------------------------
Select the appropriate number [1-2] then [enter] (press 'c' to cancel): 2

Once you have answered all the above questions the SSL client should install the cert and configure your website to redirect all traffic over HTTPS after which you should see the following message.

Congratulations! You have successfully enabled https://example.com and https://www.example.com

You should test your configuration at:
https://www.ssllabs.com/ssltest/analyze.html?d=example.com
https://www.ssllabs.com/ssltest/analyze.html?d=www.example.com
-------------------------------------------------------------------------------

IMPORTANT NOTES:
- Congratulations! Your certificate and chain have been saved at:
/etc/letsencrypt/live/example.com/fullchain.pem
Your key file has been saved at:
/etc/letsencrypt/live/example.com/privkey.pem
Your cert will expire on 2018-02-24. To obtain a new or tweaked
version of this certificate in the future, simply run certbot again
with the "certonly" option. To non-interactively renew *all* of
your certificates, run "certbot renew"
- If you like Certbot, please consider supporting our work by:

Donating to ISRG / Let's Encrypt: https://letsencrypt.org/donate
Donating to EFF: https://eff.org/donate-le

View the virtual hosts configuration by running the following command.

nano /etc/apache2/sites-available/nextcloud.conf

and you should see that an additional code block has been added to your original nextcloud configuration file.

<VirtualHost *:80>
ServerAdmin admin@example.com
DocumentRoot /var/www/html/nextcloud/
ServerName example.com
ServerAlias www.example.com

Alias /nextcloud "/var/www/html/nextcloud/"

<Directory /var/www/html/nextcloud/>
Options +FollowSymlinks
AllowOverride All
Require all granted
<IfModule mod_dav.c>
Dav off
</IfModule>
SetEnv HOME /var/www/html/nextcloud
SetEnv HTTP_HOME /var/www/html/nextcloud
</Directory>

ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined

RewriteEngine on
RewriteCond %{SERVER_NAME} =example.com [OR]
RewriteCond %{SERVER_NAME} =www.example.com
RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]

</VirtualHost>

An additional configuration file will also have been created and is located in the same directory.  This file is called nextcloud-le-ssl.conf. This is Apache SSL module configuration file and should contain the certificate definitions defined in it.

<IfModule mod_ssl.c>
<VirtualHost *:80>
ServerAdmin admin@example.com
DocumentRoot /var/www/html/nextcloud/
ServerName example.com
ServerAlias www.example.com

Alias /nextcloud "/var/www/html/nextcloud/"

<Directory /var/www/html/nextcloud/>
Options +FollowSymlinks
AllowOverride All
Require all granted
<IfModule mod_dav.c>
Dav off
</IfModule>
SetEnv HOME /var/www/html/nextcloud
SetEnv HTTP_HOME /var/www/html/nextcloud
</Directory>

ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined

SSLCertificateFile /etc/letsencrypt/live/example.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/example.com/privkey.pem
Include /etc/letsencrypt/options-ssl-apache.conf

</VirtualHost>
</IfModule> 

Now open your web browser and you should see the nextcloud wizard.

Connect to the database using the information you created and continue. After a short while you will see the following screen.

The very last job you will have to do is setup a cron job that will renew the security certificates automatically. This can be done with the following command.

crontab -e

You will now see the following options.

Select option 2 and copy and paste the following code

0 1 * * * /usr/bin/certbot renew & > /dev/null

Into the bottom of the crontab as illustrated below

This script is setup so that certbot will attempt to renew the certificate 30 days before expiry (a typical Lets Encrypt certificate is valid for 90 days).

Finally, save the file with ctrl & x

This script is setup so that certbot will attempt to renew the certificate 30 days before expiry (a typical Lets Encrypt certificate is valid for 90 days).