nextcloud installation guide

Platform: Server, PC, Notebook, Raspberry PI3 or Odroid C2, Ubuntu 16.04.1 LTS XENIAL


00. Install an Ubuntu Server 16.04.1 LTS Xenial with SSH-Server
01. Build nginx 1.11.3 with ngx_cache_purge module 2.3
02. Install PHP 7.0.8
03. Install mariaDB 10.0.25
04. Install nextcloud (9.0.53)
   Excursion: mount your NAS share to nextcloud
05. Performace tweaks
06. Server hardening
07. SSL for nextcloud (let’s encrypt)
08. Upgrade nextcloud
09. Backup nextcloud
10. Running nextcloud and other apps in parallel


v. 4.0 - August 18th, 2016: add resolver (thx Dimtirij) and added chapter 10
v. 3.0 - August 14th, 2016: add ssh hardening
v. 2.5 - August 12th, 2016: cosmetical changes
v. 2.4 - August 06th, 2016: error messages on Odroid C2
v. 2.3 - August 06th, 2016: www-data to nginx.conf and mount a NAS share
v. 2.2 - August 05th, 2016: nextcloud impressions, pdf-version
v. 2.1 - August 04th, 2016: backup, upgrade, rewrite URL, crontab
v. 2.0 - August 03rd, 2016: videos were added
v. 1.0 - August 01st, 2016: final version


00. Install An Ubuntu server

Ubuntu Server 16.04.1 LTS Xenial can be installed in less than 9 minutes including a ssh server. We built an examplarily video, based on a virtual Box.


01. build NGINX 1.11.3 with ngx_cache_purge module

nginx will be built with the module ngx_cache_purge from scratch.

We are familiar working in that directory (/usr/local/src) for compiling, so please change to it:

sudo -s
apt update && apt upgrade && apt dist-upgrade
cd /usr/local/src

Add the nginx key to your system

wget http://nginx.org/keys/nginx_signing.key
apt-key add nginx_signing.key

Add the mainline repo to your ubuntu-sources.

vi /etc/apt/sources.list.d/nginx.list
deb http://nginx.org/packages/mainline/ubuntu/ xenial nginx
deb-src http://nginx.org/packages/mainline/ubuntu/ xenial nginx

Update your software sources

apt-get update

On Odroid C2 some errors are thrown while running ‚apt update‘:
“ …N: Skipping acquire of configured file ’nginx/binary-arm64/Packages‘ as repository ‚http://nginx.org/packages/mainline/ubuntu xenial InRelease‘ doesn’t support architecture ‚arm64′
N: Skipping acquire of configured file ’nginx/binary-armhf/Packages‘ as repository ‚http://nginx.org/packages/mainline/ubuntu xenial InRelease‘ doesn’t support architecture ‚armhf‘ …“

Please ignore these errors and go ahead with the next step.


Download the build dependencies and the source code for the new nginx

apt-get build-dep nginx
apt-get source nginx

Please adjust the current release number, currently 1.11.3 (nginx-1.11.3)

mkdir nginx-1.11.3/debian/modules
cd nginx-1.11.3/debian/modules

Download the NGX_CACHE_PURGE module

Now, in the modules directory, we are going to download and extract the code for each of the modules we want to include (ngx_cache_purge 2.3).

wget https://github.com/FRiCKLE/ngx_cache_purge/archive/2.3.tar.gz

Now extract the binaries.

tar -zxvf 2.3.tar.gz

Configure the compiler args

Change back to the debian-directory and edit the compiler information <rules>

cd /usr/local/src/nginx-1.11.3/debian
vi rules

Add a „blank“ and a ‚backslash‘ at the end of the line „–with-ld-opt=“$(LDFLAGS)“ \„and add a new line „–add-module=“$(CURDIR)/debian/modules/ngx_cache_purge-2.3″“ as shown above:

...
COMMON_CONFIGURE_ARGS := \
...
 --with-ld-opt="$(LDFLAGS)" \
 --add-module="$(CURDIR)/debian/modules/ngx_cache_purge-2.3" 

Save and quit (:wq!) this file.

Compile and build the package

We will now build the debian package, please ensure you are in the nginx source directory:

cd /usr/local/src/nginx-1.11.3
dpkg-buildpackage -uc -b

After package building ist finsished please change to the src – directory.

cd /usr/local/src

Install the new nginx

First remove any old nginx fragments

sudo apt remove nginx nginx-common nginx-full

Then start installing the new nginx-webserver

dpkg --install nginx_1.11.3-1~xenial_armhf.deb

[optional run <on other hardware>:
dpkg --install nginx_1.11.3-1~xenial_amd64.deb]

Mark the nginx as „hold“ to avoid any updates to nginx using apt upgrade.

apt-mark hold nginx

Increase nginx Performance

Looking for the amount of CPUs and Process limits

grep ^processor /proc/cpuinfo | wc -l

&copy; 2016, rieger::CLOUD

Result: 4

ulimit -n

&copy; 2016, rieger::CLOUD

Result: 1024

Change the nginx.conf with regards to the previous values

vi /etc/nginx/nginx.conf

to

user www-data;
worker_processes  4;
error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;
events {
    worker_connections  1024;
    multi_accept        on;
    use                 epoll;
}
http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;
    log_format  main  '$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;
    sendfile            on;
    tcp_nopush          on;
    tcp_nodelay         on;
    keepalive_timeout   65;
    types_hash_max_size 2048;
    server_tokens off;
    include /etc/nginx/conf.d/*.conf;
}

Start and verify the running nginx with ngx_cache_purge enabled

service nginx restart && nginx -V 2>&1 | grep ngx_cache_purge -o

If ngx_cache_purge appears everything works fine.

Having regards to nextcloud you have to create web-folders, create or edit your nginx „nextcloud.conf“ and move the origin nginx „default.conf“.

sudo -s
mkdir -p /var/www/nextcloud && mkdir -p /var/nc_data && mkdir -p /var/www/letsencrypt
mv /etc/nginx/conf.d/default.conf /etc/nginx/conf.d/default.conf.bak
vi /etc/nginx/conf.d/nextcloud.conf

Paste the following lines, but please set the red once accordindingly to your environment

upstream php-handler {
    server unix:/run/php/php7.0-fpm.sock;
}
fastcgi_cache_path /usr/local/tmp/cache levels=1:2 keys_zone=NEXTCLOUD:100m inactive=60m;
map $request_uri $skip_cache {
     default 1;
     ~*/thumbnail.php 0;
     ~*/apps/galleryplus/ 0;
     ~*/apps/gallery/ 0;
}
server {
    listen 80;
    server_name yourcloud.dyndns.org 192.168.178.2;
    add_header X-Content-Type-Options nosniff;
    add_header X-Frame-Options "SAMEORIGIN";
    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;
    root /var/www/nextcloud/;
    location = /robots.txt {
        allow all;
        log_not_found off;
        access_log off;
    }
    location ^~ /.well-known/acme-challenge {
    default_type text/plain;
    root /var/www/letsencrypt;
    }
    location = /.well-known/carddav { return 301
    $scheme://$host/remote.php/dav; }
    location = /.well-known/caldav { return 301
    $scheme://$host/remote.php/dav; }
    client_max_body_size 1G;
    fastcgi_buffers 64 4K;
    gzip off;
    error_page 403 /core/templates/403.php;
    error_page 404 /core/templates/404.php;
    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/.+|core/templates/40[34])\.php(?:$|/) {
        include fastcgi_params;
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param PATH_INFO $fastcgi_path_info;
        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;
        fastcgi_send_timeout 300;
        fastcgi_connect_timeout 300;
        fastcgi_cache_bypass $skip_cache;
        fastcgi_no_cache $skip_cache;
        fastcgi_cache NEXTCLOUD;
        fastcgi_cache_valid  60m;
        fastcgi_cache_methods GET HEAD;
    }
    location ~ ^/(?:updater|ocs-provider)(?:$|/) {
        try_files $uri/ =404;
        index index.php;
    }
    location ~* \.(?:css|js)$ {
        try_files $uri /index.php$uri$is_args$args;
        add_header Cache-Control "public, max-age=7200";
        add_header X-Content-Type-Options nosniff;
        add_header X-Frame-Options "SAMEORIGIN";
        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;
        access_log off;
    }
    location ~* \.(?:svg|gif|png|html|ttf|woff|ico|jpg|jpeg)$ {
        try_files $uri /index.php$uri$is_args$args;
        access_log off;
    }
}

Create the nginx-cache directory (for ngx_cache_purge)

mkdir -p /usr/local/tmp
mkdir -p /usr/local/tmp/cache

and go ahead with the installation of PHP.


02. Install PHP 7.0.8

Install php 7.0.8 directly from the ubuntu repository

sudo -s
apt-get update && apt-get install php7.0-fpm php7.0-gd php7.0-mysql php7.0-curl php7.0-xml php7.0-zip php7.0-intl php7.0-mcrypt php7.0-mbstring php-apcu

Awesome, PHP 7 was already installed but must be configured accordingly to nextcloud.

Configure the global PHP-Config

vi /etc/php/7.0/fpm/pool.d/www.conf

Search for

Pass environment variables like LD_LIBRARY_PATH. ALL $VARIABLES are taken from the current environment

and remove all „;“ at the beginning of the following lines. Without this changes an error message would appear in the nextcloud-Adminpanel.

; 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/bin:/usr/bin:/bin
env[TMP] = /tmp
env[TMPDIR] = /tmp
env[TEMP] = /tmp

Increase pm.max-children for PHP 7

We recognized some warnings in our php.log

cat /var/log/php7.0-fpm.log
[...] WARNING: [pool www] server reached pm.max_children setting (5), consider raising it

You can solve this by editing the php-fpm-configuration

vi /etc/php/7.0/fpm/pool.d/www.conf

and change the following lines exemplarily to

...
; Note: This value is mandatory.
pm = dynamic
...
; Note: This value is mandatory.
pm.max_children = 20
...
; Default Value: min_spare_servers + (max_spare_servers - min_spare_servers) / 2
pm.start_servers = 10
...
; Note: Mandatory when pm is set to 'dynamic'
pm.min_spare_servers = 5
...
; Note: Mandatory when pm is set to 'dynamic'
pm.max_spare_servers = 10
...
; Default Value: 0
pm.max_requests = 500

To calculate the values with regards to your environment stop PHP

service php7.0-fpm stop

and run

free

to display the available memory of your system in specific:

Start PHP and display the memory needed by php

service php7.0-fpm start
ps --no-headers -o "rss,cmd" -C php-fpm7.0 | awk '{ sum+=$1 } END { printf ("%d%s\n", sum/NR/1024,"M") }'

The result should exemplarily look like:

27M

&copy; 2016, rieger::CLOUD

On

  • Rasperry Pi3 PHP 7.0 takes 27MB => 35MB for the following calculation
  • Odroid C2 PHP 7.0 takes 14MB => 20MB for the following calculation

at runtime, so we calculate with 35M (Pi3) or 20MB (OC2) to have a small buffer.

Available memory / divided to php memory usage
Rasperry Pi 3: 650M / 35M = 18,6
Odroid C2:    1800M / 20M = 90,0

On Pi3 we will apply ’20‘ for the pm.max_children value and calculate the other values as shown.

pm = dynamic
pm.max_children = 20
pm.start_servers = 10
pm.min_spare_servers = 5
pm.max_spare_servers = 10

pm.max_requests = 500

Now the warnings should disappear.

Enable APC for PHP CLI

It might be neccessary to edit the php.ini (cli) to avoid APCu-messages like „Memcache \OC\Memcache\APCu not available for local cache“ by running the following commands

vi /etc/php/7.0/cli/php.ini

Scroll to the end of this file and paste the red line priot to „; End:“

...
; Local Variables:
; tab-width: 4
apc.enable_cli = 1
; End:

adjust the PHP Settings in php-fpm.conf

vi /etc/php/7.0/fpm/php-fpm.conf

Set the following values

...
emergency_restart_threshold = 10
...
emergency_restart_interval = 1m
...
process_control_timeout = 10s
...

Restart PHP an all changes are in place

service php7.0-fpm restart && service nginx restart


03. Install databaseserver

Install mariadb 10.0.25 directly from the ubuntu repository

apt-get update && apt-get install mariadb-server

Configure and secure the databaseserver

Run the mysql_secure_installation tool

sudo -s
mysql_secure_installation

If you already set the password for the <root>-User during the installation process you can skip the first question. All the following questions should be answered with ‚Yes‘ (Y).

Modifications for nextcloud

vi /etc/mysql/my.cnf

<- Edit the global database file „my.cnf“

...
[mysqld]
binlog_format = MIXED

<- Add both rows

Create your nextcloud-database

Open the console of mariadb

mysql -uroot -p

<- Login as root to the databaseserver

create database nextcloud;
create user nextcloud@localhost identified by 'nextcloud';
grant all privileges on nextcloud.* to nextcloud@localhost;
flush privileges;
exit;

<- 1 – Create the nextcloud database
<- 2 – Create the nextcloud-dbuser
<- 3 – Grant access to the nextcloud-database
<- 4 – flush database privileges

Restart the databaseserver

service mysql restart


04. Install nextcloud

The folders for nextcloud (/var/www/nextcloud), nextcloud_data (/var/nc_data)  and let’s encrypt (/var/www/letsencrypt) were already created.

Ensure the required ACLs were set

chown -R www-data:www-data /var/www && chown -R www-data:www-data /var/nc_data

<- The owner/group-permissions are set to the webuser (www-data)

Download and extract the nextcloud-Software

Change to our working directory again

sudo -s
cd /usr/local/src

and download the current nextcloud package.

wget https://download.nextcloud.com/server/releases/nextcloud-9.0.53.tar.bz2

Extract the nextcloud package to your web-folder

tar -xjf nextcloud-9.0.53.tar.bz2 -C /var/www

Remove the sources

rm nextcloud-9.0.53.tar.bz2

and set the permissions again manually or

chown -R www-data:www-data /var/www/nextcloud && chown -R www-data:www-data /var/nc_data

by running a script. Create the script called „permissions.sh“

vi ~/permissions.sh

and paste the following commands

#!/bin/bash
find /var/www/nextcloud/ -type f -print0 | xargs -0 chmod 0640
find /var/www/nextcloud/ -type d -print0 | xargs -0 chmod 0750
chown -R www-data:www-data /var/www/letsencrypt
chown -R www-data:www-data /var/www/nextcloud/
chown -R www-data:www-data /var/www/nextcloud/apps/
chown -R www-data:www-data /var/www/nextcloud/config/
chown -R www-data:www-data /var/www/nextcloud/themes/
chown -R www-data:www-data /var/nc_data/
chown www-data:www-data /var/www/nextcloud/.htaccess
chown www-data:www-data /var/www/nextcloud/.user.ini
chown www-data:www-data /var/nc_data/.htaccess
chmod 0644 /var/www/nextcloud/.htaccess
chmod 0644 /var/www/nextcloud/.user.ini

Save and quit this script (:wq!) and make it executable

chmod u+x ~/permissions.sh

You can execute this script by running

cd ~
./permissions.sh

nextcloud installation wizard in your browser

Start your browser and call http://yourcloud

&copy; 2016 rieger::cloud

Username*: cloudchef
Password*: Your-very-Strong!PassWord
* hint: values can be selected as you want

Data folder: /var/nc_data

Datenbankuser: nextcloud
DB-Passwort: nextcloud
Datenbank-Name: nextcloud
Host: localhost

Click ,Finish setup‘ and wait few seconds … the installation will be finished and you will be prompt to the nextcloud-welcome board.

&copy; 2016 rieger::cloud

nextcloud/config.php

Some smaller changes needs to be appliedto the nextcloud-Config:

sudo -u www-data vi /var/www/nextcloud/config/config.php

<- Open the nextcloud-config as webuser (www-data)

...
 array (
 0 => 'yourcloud',
 1 => '192.168.178.2',
 ),
...

<- Replace yourcloud and the ip to your system accordingly

...
 'memcache.local' => '\OC\Memcache\APCu',
...

<- Enable the cache and the nextcloud warnings in your adminpanel will disappear

...
 'logtimezone' => 'Europe/Berlin',
...

<- Set the timezone corresponding to your system

...
 'filesystem_check_changes' => 1,
...

<- Your external Filesystem (NAS) will be checked if any filechanges are made outside nextcloud


Excursion: Mount your NAS to nextcloud

You are able to mount a NAS share to your nextcloud user files.

sudo -s
apt install cifs-utils

Store the credentials to a special file (.smbcredentials)

vi /home/<user>/.smbcredentials
username=NASuser
password=NASPassword

<- Your NAS-user and -password as plain text
<- Store and quit (:wq!)

and change the permissions to 0600

chmod 0600 /home/<user>/.smbcredentials

<- Restrict access to this file

Detect the ID of the webuser (www-data):

&copy; 2016 rieger::cloud

id www-data
vi /etc/fstab

and paste the following new line at the end of fstab

//<NAS>/<share> /var/nc_data/<nextclouduser>/files cifs user,uid=33,rw,suid,credentials=/home/<ubuntuuser>/.smbcredentials,file_mode=0770,dir_mode=0770 0 0

<- Type as one row!
<- Replace <NAS>/<share>, <nextclouduser>, <ubuntuuser> and if neccessary the uid=<33>

Mount manually

mount //<NAS>/<share>/

Unmount manually

umount //<NAS>/<share>/

It might be neccessary to rescan your data using

cd /var/www/nextcloud
sudo -u www-data php occ file:scan nextclouduser -v

&copy; 2016, rieger::CLOUD

After the occ-rescan all data from NAS will appear in your nextcloud file-app. The permissions-script <permission.sh> should be enhanced to

#!/bin/bash
find /var/www/nextcloud/ -type f -print0 | xargs -0 chmod 0640
find /var/www/nextcloud/ -type d -print0 | xargs -0 chmod 0750
chown -R www-data:www-data /var/www/letsencrypt
chown -R www-data:www-data /var/www/nextcloud/
chown -R www-data:www-data /var/www/nextcloud/apps/
chown -R www-data:www-data /var/www/nextcloud/config/
chown -R www-data:www-data /var/www/nextcloud/themes/
umount //<NAS>/<share>
chown -R www-data:www-data /var/nc_data/
mount <//NAS>/<share>
chown www-data:www-data /var/www/nextcloud/.htaccess
chown www-data:www-data /var/www/nextcloud/.user.ini
chown www-data:www-data /var/nc_data/.htaccess
chmod 0644 /var/www/nextcloud/.htaccess
chmod 0644 /var/www/nextcloud/.user.ini

Please replace the red once accordingly to your environment.


Change the max upload size

If you want to increase the MAXIMUM UPLOAD SIZE for nextcloud you have to edit the file <.user.ini>.

sudo -u www-data vi /var/www/nextcloud/.user.ini
upload_max_filesize=1024M
post_max_size=1024M
memory_limit=512M
mbstring.func_overload=0
always_populate_raw_post_data=-1
default_charset='UTF-8'
output_buffering=0

„… Nextcloud comes with its own nextcloud/.htaccess file. Because php-fpm can’t read PHP settings in .htaccess these settings must be set in the nextcloud/.user.ini file. …“

Source: https://docs.nextcloud.org

Create a cron-job

Configure the nextcloud cron-job running as Webuser (www-data)

crontab -u www-data -e

<- Edit CRONTAB as User „www-data“

*/15 * * * * php -f /var/www/nextcloud/cron.php > /dev/null 2>&1

<- Cronjob will run every 15 minutes as webuser (www-data)

or  paste it directly into crontab

crontab -u www-data -l | { cat; echo "*/15  *  *  *  * php -f /var/www/nextcloud/cron.php > /dev/null 2>&1"; } | crontab -u www-data -

nextcloud-Administrator

Logon to nextcloud as Administrator an change the AJAX-cronjob to cron:

&copy; 2016, rieger::CLOUD

The change will be stored while selecting, please have a look to the state of the cron e.g. „Last cron job execution: 9 minutes ago“…

Some impressions


05. Performace tweaks


5.1 Redis Server Installation

Run the installation of redis

sudo -s
apt-get update && apt install redis-server php-redis

Then edit the redis‘ configuration-file

vi /etc/redis/redis.conf

Change both

a) the default port to ‚0‘

# port 6379
port 0

and

b) the unixsocket-entries to

unixsocket /var/run/redis/redis.sock
unixsocketperm 770

Store and quit (:wq!) the file and grant the webuser (www-data) all privileges needed for Redis in combination with nextcloud

usermod -a -G redis www-data

Start the Redis-Server

service redis-server start

and validate the existence of

ls -la /run/redis
- and -
ls -la /var/run/redis

both files in both folders

redis-server.pid 
- and -
redis.sock.

&copy; 2016, rieger::CLOUD

&copy; 2016, rieger::CLOUD

In case files are missed in one or both folders restart your server

shutdown -r now

and validate once again. At least you have to modify the nextcloud configuration in the config.php as the webuser (www-data)

sudo -u www-data vi /var/www/nextcloud/config/config.php

and add the following lines

...
  'filelocking.enabled' => 'true',
  'memcache.locking' => '\\OC\\Memcache\\Redis',
  'redis' =>
   array (
    'host' => '/var/run/redis/redis.sock',
    'port' => 0,
    'timeout' => 0.0,
  ),
...

Restart redis and nextcloud (nginx)

service redis-server restart && service nginx restart

Our exemplarily nextcloud/config/config.php:

<?php
$CONFIG = array (
  'instanceid' => '***',
  'passwordsalt' => '***',
  'secret' => '***',
  'trusted_domains' =>
  array (
    0 => '***',
    1 => '192.168.178.2',
  ),
  'datadirectory' => '/var/nc_data',
  'overwriteprotocol' => 'https',
  'htaccess.RewriteBase' => '/',
  'dbtype' => 'mysql',
  'version' => '9.0.53.0',
  'dbname' => 'nextcloud',
  'dbhost' => 'localhost',
  'dbtableprefix' => 'oc_',
  'dbuser' => 'nextcloud',
  'dbpassword' => '***',
  'installed' => true,
  'memcache.local' => '\\OC\\Memcache\\APCu',
  'logtimezone' => 'Europe/Berlin',
  'filesystem_check_changes' => 1,
  'knowledgebaseenabled' => false,
  'quota_include_external_storage' => true,
  'filelocking.enabled' => 'true',
  'memcache.locking' => '\\OC\\Memcache\\Redis',
  'redis' =>
  array (
    'host' => '/var/run/redis/redis.sock',
    'port' => 0,
    'timeout' => 0.0,
  ),
  'cron_log' => true,
  'log_rotate_size' => 10485760,
  'debug' => false,
  'appstore.experimental.enabled' => true,
  'mail_smtpmode' => 'smtp',
  'mail_from_address' => '***',
  'mail_domain' => '***',
  'mail_smtpsecure' => 'tls',
  'mail_smtpauthtype' => 'LOGIN',
  'mail_smtpauth' => 1,
  'mail_smtphost' => '***',
  'mail_smtpport' => '587',
  'mail_smtpname' => '***',
  'mail_smtppassword' => '***',
  'loglevel' => 1,
  'theme' => '',
  'maintenance' => false,
);

5.2 Server Tweaks

Open the <fstab> and add the follwing code

sudo -s
vi /etc/fstab
...
tmpfs /tmp       tmpfs defaults,noatime,nosuid,nodev,noexec,mode=1777 0 0
tmpfs /var/tmp   tmpfs defaults,noatime,nosuid,nodev,noexec,mode=1777 0 0
...

Save and quit (:wq!) the file and mount the tmpfs-filesystem manually.

mount -a

From now it is used by your server.

To either move cache directories to ramdisk, create the file „/etc/profile.d/xdg_cache_home.sh“

sudo -s
vi /etc/profile.d/xdg_cache_home.sh

and paste the following two lines

#!/bin/bash
export XDG_CACHE_HOME="/dev/shm/.cache"

Save and quit (:wq!) the file and set permissions to

chmod +x /etc/profile.d/xdg_cache_home.sh

We also discussed the use of assett-piplineing for nextcloud in the forum. As a result we won’t configure that anymore.


06. Server hardening


6.1 Disable IPv6

We recommend to disable IPv6 if you are not using it.

sudo -s
sudo ip6tables -P INPUT DROP
sudo ip6tables -P OUTPUT DROP
sudo ip6tables -P FORWARD DROP

Edit sysctl.conf as follows

vi /etc/sysctl.conf
...
net.ipv6.conf.all.disable_ipv6 = 1
net.ipv6.conf.default.disable_ipv6 = 1
net.ipv6.conf.lo.disable_ipv6 = 1
...

and reload the configuration by

sudo -s
sysctl -p

Disable IPv6 in the firewall (ufw)

Edit the ufw-config

sudo -s
vi /etc/default/ufw

and set IPV6 to ’no‘ or respectively comment it out.

#IPV6=yes
IPV6=no

6.2 Enable and configure the ufw

Then re-enable the ufw and you are set.

ufw disable
ufw enable

or restart the ufw

service ufw restart

In specific we will allow ownly the four needed services for nextcloud: http, https, ssh and mysql

ufw allow http
ufw allow https
ufw allow ssh
ufw logging medium

In addition we will set a deny rule for all the other incoming requests

ufw default deny incoming

The status should look like

ufw status verbose
Status: active
Logging: on (medium)
Default: deny (incoming), allow (outgoing), disabled (routed)
New profiles: skip

To                         Action      From
--                         ------      ----
22                         ALLOW IN    Anywhere
443                        ALLOW IN    Anywhere
80                         ALLOW IN    Anywhere

6.3 Prevent IP Spoofing

Switch back to your terminal and type the following

sudo -s
vi /etc/host.conf

Add/edit the following lines

# order hosts,bind
# multi on
order bind,hosts
nospoof on

Reboot your server to ensure all changes beeing in place.


6.4 Check your environment using nmap

Install nmap and check your system.

sudo -s
apt install nmap

Run both

nmap -v -sT localhost

Your output should look similar to mine

...
Initiating Connect Scan at 09:55
Scanning localhost (127.0.0.1) [1000 ports]
Discovered open port 3306/tcp on 127.0.0.1
Discovered open port 22/tcp on 127.0.0.1
Discovered open port 443/tcp on 127.0.0.1
Discovered open port 80/tcp on 127.0.0.1
Completed Connect Scan at 09:55, 0.07s elapsed (1000 total ports)
Nmap scan report for localhost (127.0.0.1)
Host is up (0.00043s latency).
Not shown: 996 closed ports
PORT     STATE SERVICE
22/tcp   open  ssh
80/tcp   open  http
443/tcp  open  https
3306/tcp open  mysql

Read data files from: /usr/bin/../share/nmap
Nmap done: 1 IP address (1 host up) scanned in 0.23 seconds
           Raw packets sent: 0 (0B) | Rcvd: 0 (0B)
nmap -v -sS localhost

Your output should look similar to mine once more.

...
Initiating SYN Stealth Scan at 09:57
Scanning localhost (127.0.0.1) [1000 ports]
Discovered open port 443/tcp on 127.0.0.1
Discovered open port 22/tcp on 127.0.0.1
Discovered open port 80/tcp on 127.0.0.1
Discovered open port 3306/tcp on 127.0.0.1
Increasing send delay for 127.0.0.1 from 0 to 5 due to 391 out of 1303 dropped probes since last increase.
Increasing send delay for 127.0.0.1 from 5 to 10 due to 11 out of 24 dropped probes since last increase.
Increasing send delay for 127.0.0.1 from 10 to 20 due to 11 out of 24 dropped probes since last increase.
Increasing send delay for 127.0.0.1 from 20 to 40 due to 11 out of 24 dropped probes since last increase.
Increasing send delay for 127.0.0.1 from 40 to 80 due to 11 out of 30 dropped probes since last increase.
Completed SYN Stealth Scan at 09:57, 22.20s elapsed (1000 total ports)
Nmap scan report for localhost (127.0.0.1)
Host is up (0.000089s latency).
Not shown: 996 closed ports
PORT     STATE SERVICE
22/tcp   open  ssh
80/tcp   open  http
443/tcp  open  https
3306/tcp open  mysql

Read data files from: /usr/bin/../share/nmap
Nmap done: 1 IP address (1 host up) scanned in 22.42 seconds
           Raw packets sent: 1448 (63.712KB) | Rcvd: 2900 (121.808KB)

6.5 Disable CTRL+ALT+DEL

Stop ctrl+alt+del from rebooting the server

sudo -s

Run the following commands

systemctl mask ctrl-alt-del.target
systemctl daemon-reload

FAIL2BAN

We will install <fail2ban> to avoid any kind of bruteforce or ddos attacks.

sudo -s
apt-get update && apt install fail2ban

Create the nextcloud-filter for fail2ban

 vi /etc/fail2ban/filter.d/nextcloud.conf
[Definition]
failregex={"reqId":".*","remoteAddr":".*","app":"core","message":"Login failed: '.*' \(Remote IP: '<HOST>'\)","level":2,"time":".*"}
ignoreregex =

and add the following code at the end of the file <jail.conf>

vi /etc/fail2ban/jail.conf
...
[nextcloud]
enabled = true
port = 80,443
protocol = tcp
filter = nextcloud
maxretry = 3
bantime = 180
logpath = /var/nc_data/owncloud.log

<- if neccessary adjuste your path to the nextcloud-logfile

Start fail2ban-service and become familiar to the fail2ban status

service fail2ban restart
fail2ban-client status nextcloud

&copy; 2016, rieger::CLOUD

Logon to your nextcloud using wrong credentials for at least three times. The browser will display an error message and the fail2ban-status changed as shown exemplarily in the screenshot

&copy; 2016, rieger::CLOUD

You can remove the locked IP (banip) using this command

fail2ban-client set nextcloud unbanip <Banned IP>

6.7 Install POSTFIX to receive server mails

Please install two packages: postfix and libsasl2-modules

sudo -s
apt install postfix libsasl2-modules mailutils

and start configure your mailserver.

When the postfix-Installationscreen appears select <sattelitesystem>

&copy; 2016, rieger::CLOUD

Postfix will ask you for the system emailname, you can confirm the shown entry e.g. yourcloud. Then you were asked for the smtp-relayservername e.g. w12345.kasserver.com. Please fill in your according mailservername.

&copy;2016, rieger::CLOUD

Finish the installation <OK>. Now edit the configuration of postfix

sudo -s
vi /etc/postfix/main.cf

and add the following lines

...
smtp_sasl_auth_enable = yes
smtp_sasl_security_options = noanonymous
smtp_sasl_password_maps = hash:/etc/postfix/sasl_password

Save and quit (:wq!) this file.

Our exemplarily main.cf:

smtpd_banner = $myhostname ESMTP $mail_name (Ubuntu)
biff = no
append_dot_mydomain = no
readme_directory = no
smtpd_relay_restrictions = permit_mynetworks permit_sasl_authenticated defer_unauth_destination
myhostname = YOURCLOUD
alias_maps = hash:/etc/aliases
alias_database = hash:/etc/aliases
mydestination = $myhostname, YOURCLOUD, localhost.localdomain, localhost
relayhost = [w123456.kasserver.com]:587
smtp_sasl_auth_enable = yes
smtp_sasl_security_options = noanonymous
smtp_sasl_password_maps = hash:/etc/postfix/sasl_password
sender_canonical_maps = hash:/etc/postfix/sender_canonical
mynetworks = 127.0.0.0/8
mailbox_size_limit = 0
recipient_delimiter = +
inet_interfaces = loopback-only
inet_protocols = all

Create a new file containing your credentials to connect to your mailserver.

vi /etc/postfix/sasl_password

Enter your credentials like exemplarily shown

w12345.kasserver.com a987654:PassWorD

and change the access level of this file to 0600.

chmod 600 /etc/postfix/sasl_password

At least we promote the information to postfix.

postmap hash:/etc/postfix/sasl_password

As default mails would be sent as user@hostname (e.g. root@localhost), but a lot of mailserver would reject those mails. That’s why we add a new row to postfix configuration file:

sudo -s
vi /etc/postfix/main.cf

Add the following line to the config file

...
sender_canonical_maps = hash:/etc/postfix/sender_canonical

Save and quit (:wq!) the configuration and create the referred new file

vi /etc/postfix/sender_canonical

Add both lines and adjust the parameters according to your environment

root your@mail.com
www-data your@mail.com

This will assign your emailadress to the root and www-data users. We have to promote this information to postfix again

postmap /etc/postfix/sender_canonical

Finally we add postfix to the autostart and start the service

update-rc.d postfix defaults
service postfix restart

From now, you are already able to send system mails. Please verify the functionality

vi testmail.txt

Add any kind of text to your demofile, e.g.

My first system mail

Save and quit the testfile (:wq!) and send your first manual system mail

mail -s "yourcloud - subject" your@mail.com < testmail.txt

Check the logfile

cat /var/log/mail.log

and also check your mailclient if you already received that mail.

FAIL2BAN – system mails

We substitute the root-User in the fail2ban-config to receive status mails of fail2ban in the future. Those mails will contain both, the fail2ban-status (stopped/started) and in case of failed logins also the banned ip(’s). Edit the fail2ban configuration file

sudo -s
vi /etc/fail2ban/jail.conf

and substitute at least the red marked parameters according to your system:

# ACTIONS
#

# Some options used for actions

# Destination email address used solely for the interpolations in
# jail.{conf,local,d/*} configuration files.
destemail = your@mail.com

# Sender email address used solely for some actions
sender = your@mail.com

# E-mail action. Since 0.8.1 Fail2Ban uses sendmail MTA for the
# mailing. Change mta configuration parameter to mail if you want to
# revert to conventional 'mail'.
# mta = sendmail
mta = mail
...
# Choose default action.  To change, just override value of 'action' with the
# interpolation to the chosen action shortcut (e.g.  action_mw, action_mwl, etc) in jail.local
# globally (section [DEFAULT]) or per specific section
# action = %(action_)s
action = %(action_mwl)s
...

Save and quit (:wq!) the fail2ban configuration, restart fail2ban

service fail2ban restart

and receive emails from FAIL2BAN.


6.8 Apticron

If you use APTICRON, your system will send emails in case of available systemupdates.

sudo -s
apt install apticron

After havin installed APTICRON you should edit the config and substitute at least your EMAIL, SYSTEM, NOTIFY_NO_UPDATES and CUSTOM_FROM.

vi /etc/apticron/apticron.conf
...
EMAIL="your@mail.com"
...
SYSTEM="yourcloud.dyndns.org"
...
NOTIFY_NO_UPDATES="1"
...
CUSTOM_SUBJECT="yourcloud: updates available"
...
CUSTOM_NO_UPDATES_SUBJECT="yourcloud: no updates available"
...
CUSTOM_FROM="your@mail.com"
...

To run and check APTICRON just call

sudo apticron

and you will receive an email sent by APTICRON. Now you are a little bit more secure.


Two (2)-Factor-Authentication (2FA) for SSH

The following steps are system relevant (critical) and only recommended for advanced linux users. If the ssh configuration will fail, you won’t be able to login to your system via ssh anymore. The mandatory prerequisite is a ssh server that you can log on using private/public key only!

Install the software for 2FA (Two-Factor-Authentication) with googles authenticator app

sudo -s
apt install libpam-google-authenticator

Leave the root-Shell and run the following command as your user

exit
google-authenticator

You will be asked for:

Do you want authentication tokens to be time-based (y/n) y
Do you want me to update your "~/.google_authenticator" file (y/n) y
Do you want to disallow multiple uses of the same authentication
token? This restricts you to one login about every 30s, but it increases
your chances to notice or even prevent man-in-the-middle attacks (y/n) y
By default, tokens are good for 30 seconds and in order to compensate for
possible time-skew between the client and the server, we allow an extra
token before and after the current time. If you experience problems with poor
time synchronization, you can increase the window from its default
size of 1:30min to about 4min. Do you want to do so (y/n) n
If the computer that you are logging into isn't hardened against brute-force
login attempts, you can enable rate-limiting for the authentication module.
By default, this limits attackers to no more than 3 login attempts every 30s.
Do you want to enable rate-limiting (y/n) y

Change to the root-Shell again

sudo -s

and configure your ssh server

vi /etc/pam.d/sshd

Change the file to

# PAM configuration for the Secure Shell service

# Standard Un*x authentication.
# @include common-auth
auth required pam_google_authenticator.so
...

Save and quit (:wq!) teh file.

Edit your SSH-config to examplarily mine

vi /etc/ssh/sshd_config
Port 22
Protocol 2
HostKey /etc/ssh/ssh_host_rsa_key
HostKey /etc/ssh/ssh_host_dsa_key
HostKey /etc/ssh/ssh_host_ecdsa_key
HostKey /etc/ssh/ssh_host_ed25519_key
UsePrivilegeSeparation yes
KeyRegenerationInterval 3600
ServerKeyBits 1024
SyslogFacility AUTH
LogLevel INFO
LoginGraceTime 30
PermitRootLogin no
StrictModes yes
RSAAuthentication yes
PubkeyAuthentication yes
IgnoreRhosts yes
RhostsRSAAuthentication no
HostbasedAuthentication no
IgnoreUserKnownHosts yes
PermitEmptyPasswords no
ChallengeResponseAuthentication yes
PasswordAuthentication no
X11Forwarding no
X11DisplayOffset 10
PrintMotd no
PrintLastLog no
TCPKeepAlive yes
Banner /etc/ssh/issue
AcceptEnv LANG LC_*
Subsystem sftp /usr/lib/openssh/sftp-server
UsePAM yes
AuthenticationMethods publickey,keyboard-interactive
AllowUsers your_ssh_user(s)

Restart your ssh server and re-logon to your server. You will be prompt for a second factor.

&copy; 2016, rieger::CLOUD

Start your google authenticator app (on iOS or on android) and read your second factor.


07. SSL for nextcloud (let’s encrypt)

We will secure nextcloud using Let’sEncrypt-certificates with the goal to achieve an A+ rating from QUALYS SSL LABS.

&copy; 2016, rieger::CLOUD

It depends on a nextcloud-instance that is reachable and available over the internet using both, TCP-Port 80 for http and TCP-Port 443 for https. After the successfull implementation of ssl we will forward the default http-port :80 to tcp-port :443 (ssl) … so let’s start.

Ensure that your server is reachable over the internet via

http://yourcloud.dyndns.org

as mentioned in the nginx configuration „nextcloud.conf“.

Download the letsencrypt-clientsoftware

cd ~
sudo -s
git clone https://github.com/letsencrypt/letsencrypt

and call the let’s encrypt-client

cd letsencrypt
sudo -H ./letsencrypt-auto certonly -a webroot --webroot-path=/var/www/letsencrypt --rsa-key-size 4096

Finally the client should display a success-message and store all the cert-files to

ls -la /etc/letsencrypt/live/<YOURCLOUD.DYNDNS-ADRESS>
cert.pem - public key
chain.pem - public key from keychain
fullchain.pem - bundle (cert.pem + chain.pem)
privkey.pem - private Key

In addition we enhance security by using the Diffie-Hellman-Parameter (2048)

mkdir -p /etc/nginx/ssl
openssl dhparam -out /etc/ssl/certs/dhparam.pem 2048

<- will take some minutes

or (more secure 4096 – but will take a long time to calculate)

openssl dhparam -out /etc/ssl/certs/dhparam.pem 4096

<- will take some hours

Finally apply the access level of all the cert-files to 0600

sudo -s
chmod 600 /etc/letsencrypt/live/<YOURCLOUD...>/fullchain.pem
chmod 600 /etc/letsencrypt/live/<YOURCLOUD...>/privkey.pem
chmod 600 /etc/letsencrypt/live/<YOURCLOUD...>/chain.pem
chmod 600 /etc/letsencrypt/live/<YOURCLOUD...>/cert.pem
chmod 600 /etc/ssl/certs/dhparam.pem

After all these (initial) steps we have to declare a rewrite rule to forward incoming requests from port :80 to port :443, add ssl in general and enable the hsts-feature in the nextcloud.conf.

Stop nginx

service nginx stop

First create a backup (nextcloud.conf.http)

cp /etc/nginx/conf.d/nextcloud.conf /etc/nginx/conf.d/nextcloud.conf.http

and then edit nextcloud.conf

vi /etc/nginx/conf.d/nextcloud.conf

Paste the red once and substitute the values to your environment accordingly:

upstream php-handler {
    server unix:/run/php/php7.0-fpm.sock;
}
fastcgi_cache_path /usr/local/tmp/cache levels=1:2 keys_zone=NEXTCLOUD:100m inactive=60m;
map $request_uri $skip_cache {
     default 1;
     ~*/thumbnail.php 0;
     ~*/apps/galleryplus/ 0;
     ~*/apps/gallery/ 0;
}
server {
    listen 80;
    server_name yourcloud.dyndns.org 192.168.178.2;
    return 301 https://$server_addr$request_uri;
    # Use this if you always want to redirect to the DynDNS address
    # (no local access ->). <return 301 https://$server_name$request_uri;>
}
server {
    listen 443 ssl http2;
    server_name yourcloud.dyndns.org 192.168.178.2;
    ssl_certificate /etc/letsencrypt/live/yourcloud.dyndns.org/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/yourcloud.dyndns.org/privkey.pem;
    ssl_protocols TLSv1.2; 
    ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!3DES:!MD5:!PSK';
    ssl_dhparam /etc/ssl/certs/dhparam.pem;
    ssl_ecdh_curve secp521r1;
    ssl_prefer_server_ciphers on; 
    ssl_stapling on;
    ssl_stapling_verify on;
    resolver 8.8.8.8
    # or your prefered resolver/dns ip
    ssl_trusted_certificate /etc/letsencrypt/live/yourcloud.dyndns.org/fullchain.pem;
    ssl_session_timeout 24h;
    ssl_session_cache shared:SSL:50m;
    ssl_session_tickets off;
    add_header Strict-Transport-Security "max-age=15768000; includeSubdomains; preload";
    add_header X-Content-Type-Options nosniff;
    add_header X-Frame-Options "SAMEORIGIN";
    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;
    root /var/www/nextcloud;
    location = /robots.txt {
        allow all;
        log_not_found off;
        access_log off;
    }
    location ^~ /.well-known/acme-challenge {
    default_type text/plain;
    root /var/www/letsencrypt;
    }
    location = /.well-known/carddav { return 301
    $scheme://$host/remote.php/dav; }
    location = /.well-known/caldav { return 301
    $scheme://$host/remote.php/dav; }
    client_max_body_size 1G;
    fastcgi_buffers 64 4K;
    gzip off;
    error_page 403 /core/templates/403.php;
    error_page 404 /core/templates/404.php;
    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/.+|core/templates/40[34])\.php(?:$|/) {
        include fastcgi_params;
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param PATH_INFO $fastcgi_path_info;
        fastcgi_param HTTPS on;
        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;
        fastcgi_send_timeout 300;
        fastcgi_connect_timeout 300;
        fastcgi_cache_bypass $skip_cache;
        fastcgi_no_cache $skip_cache;
        fastcgi_cache NEXTCLOUD;
        fastcgi_cache_valid  60m;
        fastcgi_cache_methods GET HEAD;
    }
    location ~ ^/(?:updater|ocs-provider)(?:$|/) {
        try_files $uri/ =404;
        index index.php;
    }
    location ~* \.(?:css|js)$ {
        try_files $uri /index.php$uri$is_args$args;
        add_header Cache-Control "public, max-age=7200";
        add_header X-Content-Type-Options nosniff;
        add_header X-Frame-Options "SAMEORIGIN";
        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;
        access_log off;
    }
    location ~* \.(?:svg|gif|png|html|ttf|woff|ico|jpg|jpeg)$ {
        try_files $uri /index.php$uri$is_args$args;
        access_log off;
    }
}

Download: nextcloud.conf

Create a backup (nextcloud.conf.https) of this new configuration

cp /etc/nginx/conf.d/nextcloud.conf /etc/nginx/conf.d/nextcloud.conf.https

From now your nextcloud will only be available using ssl (https) but not via the default Port :80 anymore. Proceed a security check using QUALYS SSL LABS, fill in your URL (yourcloud.dyndns.org) and enjoy your security-results!

&copy; 2016, rieger::CLOUD

Certificate renewal

Every 90 days you have to renew your certificates by restoring nextcloud.conf.http and running the following letsencrypt-commands:

cp /etc/nginx/conf.d/nextcloud.conf.http /etc/nginx/conf.d/nextcloud.conf

Restart nginx:

service nginx restart

Change to the ~/letsencrypt directory and run the tool again.

cd ~/letsencrypt
sudo -H ./letsencrypt-auto certonly -a webroot --webroot-path=/var/www/letsencrypt --rsa-key-size 4096

You will be asked for the corresponding domain-name (YOURCLOUD_DYNDNS.ADRESS) and your concern. Type in your domain-name and press ‚OK‘. Then select ‚2‘ to renew your certificates.

&copy; 2016, rieger::CLOUD

&copy; 2016, rieger::CLOUD

The renewal process will start and finish few seconds later. Your certificates are valid for further 90 days.

&copy; 2016, rieger::CLOUD

Restore the nextcloud.conf.https configuration

cp /etc/nginx/conf.d/nextcloud.conf.https /etc/nginx/conf.d/nextcloud.conf

and restart nginx again.

service nginx restart

For the future you just have to copy nextcloud.conf.*-files, restart nginx and run a single line command to renew your ssl-certificates.


08 UPDATEs

Exemplarily upgrade scenario from nextcloud 9.x to nextcloud 10 beta. Please backup your system before you start any updates!

Stop nginx, back up your database and create a backup of your nextcloud config.php

service nginx stop
mysqldump --lock-tables -unextcloud -pnextcloud nextcloud --add-drop-table --allow-keywords --complete-insert --quote-names > ~/nextcloud-db.sql
cp /var/www/nextcloud/config/config.php ~

Download the latest sources (nextcloud 10 beta) from nextcloud.com

wget https://download.nextcloud.com/server/prereleases/nextcloud-10.0beta.tar.bz2

Move the old nextcloud-folder and extract the sources to /var/www

mv /var/www/nextcloud /var/www/_nextcloud
tar -xjf nextcloud-10.0beta.tar.bz2 -C /var/www

Copy the config.php to the new release

cp ~/config.php /var/www/nextcloud/config

Start nginx, run permissions.sh and start upgrading your Cloud

service nginx start
cd ~
./permissions.sh

&copy; 2016, rieger::CLOUD

Re-Enable your apps, remove the sources and the old _nextcloud-folder

rm -R /var/www/_nextcloud
rm ~/config.php

and finally become more familiar using occ

cd /var/www/nextcloud
sudo -u www-data php occ -V
sudo -u www-data php occ app:list
sudo -u www-data php occ config:list

After having successfully tested the new release you can either delete the database backup

rm ~/nextcloud-db.sql


09 Backup nextcloud

Create a shellscript and let cron handle your regulary backups automatically

Creat a shellscript

Create the backup.sh file

vi ~/backup.sh

and paste the following lines

#!/bin/sh
cd /
echo  START: $(date +"%Y.%m.%d-%H:%M")
rsync -aR var/www/nextcloud/ home/next/bkup
mysqldump --lock-tables -unextcloud -pnextcloud nextcloud --add-drop-table --allow-keywords --complete-insert --quote-names > home/next/bkup/backup.sql
tar -czf home/next/bkup/sicherungen/$(date +%Y%m%d_%H%M%S)_backup.tar.gz home/next/bkup/var/ home/next/bkup/backup.sql
rm home/next/bkup/backup.sql
echo ---------------------------------
echo  ENDE: $(date +"%Y.%m.%d-%H:%M")
echo ---------------------------------
exit 0

Create the backup folders

mkdir -p ~/bkup && mkdir -p ~/bkup/sicherungen

Create a cron-job

sudo -s
vi /etc/crontab

<- edit crontab-file

55 23 * * * root /home/next/backup.sh >> /home/next/bkup/cron.log

Make the script executable

chmod u+x ~/backup.sh

You can check the cron.log and the other files

cat /home/next/bkup/cron.log
ls bkup
ls bkup/sicherungen


10 running nextcloud and other apps in parallel

As a prerequisite your nextcloud is reachable via ssl using letsencrypt. After having made the following changes your nextcloud will be reachable by a new URL: https://your.dyndns.org/nextcloud.

You will find exemplarily nginx-configurations to run nextcloud in parallel to other applications like roundcube, wordpress or ampache. In addition you won’t copy your config-files anymore to renew your ssl-certificates, because this is handled via internal proxy:

Stop your nginx-webserver and move your nextcloud.con file to nextcloud.conf.bak.

sudo -s
service nginx stop
mv /etc/nginx/conf.d/nextcloud.conf /etc/nginx/conf.d/nextcloud.conf.bak

Now create a gateway-configuration that will handle all web-calls internaly:

vi /etc/nginx/conf.d/gateway.conf

Paste the following lines

upstream php-handler {
    server unix:/run/php/php7.0-fpm.sock;
}
server {
listen 80 default_server;
server_name your.dyndns.org 192.168.178.2;
root /var/www;
location ^~ /.well-known/acme-challenge {
proxy_pass http://127.0.0.1:81;
proxy_redirect off;
}
location / {
 return 301 https://$server_name$request_uri;
 } 
}
 server {
 listen 443 ssl http2;
 server_name your.dyndns.org 192.168.178.2;
 ssl on;
 ssl_certificate /etc/letsencrypt/live/your.dyndns.org/fullchain.pem;
 ssl_certificate_key /etc/letsencrypt/live/your.dyndns.org/privkey.pem;
 ssl_protocols TLSv1.2;
 ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!3DES:!MD5:!PSK';
 ssl_dhparam /etc/ssl/certs/dhparam.pem;
 ssl_ecdh_curve secp521r1;
 ssl_prefer_server_ciphers on;
 ssl_stapling on;
 ssl_stapling_verify on;
 resolver 192.168.178.1;
 ssl_trusted_certificate /etc/letsencrypt/live/your.dyndns.org/fullchain.pem;
 ssl_session_timeout 24h;
 ssl_session_cache shared:SSL:50m;
 ssl_session_tickets off;
 add_header Strict-Transport-Security "max-age=63072000; includeSubdomains; preload";
 add_header X-Content-Type-Options nosniff;
 add_header X-Frame-Options "SAMEORIGIN";
 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 = / {
  rewrite ^ /nextcloud;
 }
 location ^~ /nextcloud {
 client_max_body_size 1G;
 proxy_connect_timeout 300;
 proxy_send_timeout 300;
 proxy_read_timeout 300;
 send_timeout 300;
 proxy_set_header Host $host;
 proxy_set_header X-Real-IP $remote_addr;
 proxy_pass http://127.0.0.1:82;
 proxy_redirect off;
 }
 # e.g. roundcube (emails) or wordpress
 location ^~ /emails {
 client_max_body_size 1G;
 proxy_connect_timeout 300;
 proxy_send_timeout 300;
 proxy_read_timeout 300;
 send_timeout 300;
 proxy_set_header Host $host;
 proxy_set_header X-Real-IP $remote_addr;
 proxy_pass http://127.0.0.1:83;
 proxy_redirect off;
 }
}

Save and quit (:wq!) the file.

Please ensure having substituted the red once accordingly to your environment.

Then we create the nextcloud.configuration very similar to the previous one:

vi /etc/nginx/conf.d/nextcloud.conf

Paste the following lines without making any changes

fastcgi_cache_path /usr/local/tmp/cache levels=1:2 keys_zone=NEXTCLOUD:100m inactive=60m;
 map $request_uri $skip_cache {
     default 1;
     ~*/thumbnail.php 0;
     ~*/apps/galleryplus/ 0;
     ~*/apps/gallery/ 0;
}
server {
    listen 82;
    server_name 127.0.0.1;
    proxy_set_header Strict-Transport-Security "max-age=15768000; includeSubDomains; preload;";
    proxy_set_header X-Content-Type-Options nosniff;
    proxy_set_header X-Frame-Options "SAMEORIGIN";
    proxy_set_header X-XSS-Protection "1; mode=block";
    proxy_set_header X-Robots-Tag none;
    proxy_set_header X-Download-Options noopen;
    proxy_set_header X-Permitted-Cross-Domain-Policies none;
    root /var/www/;
    location = /robots.txt {
        allow all;
        log_not_found off;
        access_log off;
    }
    location = /.well-known/carddav { return 301 $scheme://$host/nextcloud/remote.php/dav; }
    location = /.well-known/caldav { return 301 $scheme://$host/nextcloud/remote.php/dav; }
    location /.well-known/acme-challenge { }
    location ^~ /nextcloud {
    client_max_body_size 1G;
    fastcgi_buffers 64 4K;
    gzip off;
    error_page 403 /nextcloud/core/templates/403.php;
    error_page 404 /nextcloud/core/templates/404.php;
    location /nextcloud {
     rewrite ^ /nextcloud/index.php$uri;
     }
    location ~ ^/nextcloud/(?:build|tests|config|lib|3rdparty|templates|data)/ {
     deny all;
     }
    location ~ ^/nextcloud/(?:\.|autotest|occ|issue|indie|db_|console) {
     deny all;
    }
    location ~ ^/nextcloud/(?:index|remote|public|cron|core/ajax/update|status|ocs/v[12]|updater/.+|ocs-provider/.+|core/templates/40[34])\.php(?:$|/) {
    include fastcgi_params;
    fastcgi_split_path_info ^(.+\.php)(/.+)$;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    fastcgi_param PATH_INFO $fastcgi_path_info;
    #fastcgi_param HTTPS on;
    fastcgi_pass php-handler;
    fastcgi_cache_bypass $skip_cache;
    fastcgi_no_cache $skip_cache;
    fastcgi_cache NEXTCLOUD;
    fastcgi_cache_valid  60m;
    fastcgi_cache_methods GET HEAD;
    fastcgi_param modHeadersAvailable true; #Avoid sending the security headers twice
    fastcgi_param front_controller_active true;
    fastcgi_intercept_errors on;
    fastcgi_read_timeout 300;
    fastcgi_send_timeout 300;
    fastcgi_connect_timeout 300;
    fastcgi_param PHP_VALUE "upload_max_filesize = 1G
                             post_max_size = 1G
                             max_execution_time = 3600";
    fastcgi_param REMOTE_ADDR $http_x_real_ip;
    }
    location ~ ^/nextcloud/(?:updater|ocs-provider)(?:$|/) {
     try_files $uri/ =404;
     index index.php;
    }
    location ~* \.(?:css|js)$ {
    try_files $uri /nextcloud/index.php$uri$is_args$args;
    proxy_set_header Cache-Control "public, max-age=7200";
    proxy_set_header Strict-Transport-Security "max-age=15768000; includeSubDomains; preload;";
    proxy_set_header X-Content-Type-Options nosniff;
    proxy_set_header X-Frame-Options "SAMEORIGIN";
    proxy_set_header X-XSS-Protection "1; mode=block";
    proxy_set_header X-Robots-Tag none;
    proxy_set_header X-Download-Options noopen;
    proxy_set_header X-Permitted-Cross-Domain-Policies none;
    access_log off;
    }
    location ~* \.(?:svg|gif|png|html|ttf|woff|ico|jpg|jpeg)$ {
    try_files $uri /nextcloud/index.php$uri$is_args$args;
    access_log off;
        }
    }
}

Save and quit (:wq!) the file.

We will now create the letsencrypt-configuration file

vi /etc/nginx/conf.d/letsencrypt

Paste the following lines

server {
 listen 81;
 server_name 127.0.0.1;
 location ^~ /.well-known/acme-challenge {
 default_type text/plain;
 root /var/www/letsencrypt;
 }
}

Save and quit (:wq!) the file!

At least we create the roundcube (emails) configuration file. You may use this file as a template for other applications like wordpress, ampache etc., but don’t forget to change the proxy_pass http://127.0.0.1:83 (e.g. to proxy_pass http://127.0.0.1:84;) in your gateway.conf and the listen port (e.g. listen 84) in your new application *.conf.

Create the emails-configuration file

vi /etc/nginx/conf.d/emails

Paste the following lines

server {
    listen 83;
    server_name 127.0.0.1;
    proxy_set_header Strict-Transport-Security "max-age=15768000; includeSubDomains; preload;";
    proxy_set_header X-Content-Type-Options nosniff;
    proxy_set_header X-Frame-Options "SAMEORIGIN";
    proxy_set_header X-XSS-Protection "1; mode=block";
    proxy_set_header X-Robots-Tag none;
    proxy_set_header X-Download-Options noopen;
    proxy_set_header X-Permitted-Cross-Domain-Policies none;
    root /var/www/;
    location = /robots.txt {
        allow all;
        log_not_found off;
        access_log off;
    }
    location ^~ /emails {
        index index.php;
        client_max_body_size 1G;
        fastcgi_buffers 64 4K;
            location ~ \.php$ {
            include fastcgi_params;
            fastcgi_split_path_info ^(.+\.php)(/.+)$;
            fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
            fastcgi_param PATH_INFO $fastcgi_path_info;
            fastcgi_param modHeadersAvailable true; #Avoid sending the security headers twice
            fastcgi_param front_controller_active true;
            fastcgi_pass php-handler;
            fastcgi_intercept_errors on;
            fastcgi_read_timeout 300;
            fastcgi_send_timeout 300;
            fastcgi_connect_timeout 300;   
            fastcgi_param PHP_VALUE "upload_max_filesize = 1G
            post_max_size = 1G
            max_execution_time = 3600";            
            fastcgi_param REMOTE_ADDR $http_x_real_ip;
            }
        }
    }

Save and quit (:wq!) the file!

Check your configuration changes by

nginx -t

If no errors occurs you can restart nginx (and redis, php)

service redis-server restart && service php7.0-fpm restart && service nginx start

and call your applications as follows:

nextcloud: https://your.dyndns.org/nextcloud/
roundcube: https://your.dyndns.org/emails/

&copy; 2016, rieger::CLOUD &copy; 2016, rieger::CLOUD

If someone calls your URL without any suffix, nginx will forward the call to /nextcloud/.

You can now renew your certificates without making any changes to your environment by running the following call

cd ~/letsencrypt
sudo -H ./letsencrypt-auto certonly -a webroot --webroot-path=/var/www/letsencrypt --rsa-key-size 4096

download: nginx-configuration-files


Have fun and enjoy your nextCLOUD …
© 2016, rieger::CLOUD (Carsten Rieger)


Reviewed by and many thanks to Toppy and enoch85 and Dimtirij


pdf