Nextcloud 15 installation guide (Ubuntu/NGINX)


Nextcloud advanced installation guide


Following this guide you will be able to install and configure Nextcloud 15 latest based on Ubuntu 18.04.x LTS, NGINX 1.15.8, TLSv1.2 or TLSv1.3, PHP 7.3new, MariaDB 10.3, Redis, fail2ban, firewall (ufw) and will achieve an A+ rating from both, Nextcloud and Qualys SSL Labs. We will request and implement your ssl certificate(s) from Let’s Encrypt in chapter 5. You only have to ammend the red marked values (YOUR.DEDYN.IO, 192.168.2.x, ssh port 22) regarding your environment!


Pre-requirements

From my perspective the requirements for this guide may be rated as low: you only have to

  • provide a 64Bit Server (e.g. Intel NUC),
  • forward two ports (80 and 443) from internet (your router e.g. FritzBox or Speedport) to your internal Nextcloud server
  • and install the operating system Ubuntu 18.04 LTS (64Bit).

Last Updates:

January, 17th 2019:

– made changes to the feature policy in the header.conf

… the entire update history


Table of content

  1. Prepare your server and install NGINX 1.15.8
  2. PHP 7.3
  3. MariaDB 10.3
  4. Redis
  5. Nextcloud (SSL enabled, A+)
  6. fail2ban and firewall (ufw)
  7. Monitor your server using netdata
  8. Mount additonal storage to your Nextcloud
  9. Install postfix and configure system notification mails
  10. A second factor for ssh (2FA)

1. Prepare your server and install NGINX

If you are interested in compiling NGINX and operate with OpenSSL 1.1.1 + TLS 1.3 you may find detailed instructions here.

sudo -s
apt install wget gnupg2 -y
cd /usr/local/src
mv /etc/apt/sources.list /etc/apt/sources.list.bak && touch /etc/apt/sources.list
cat <<EOF >>/etc/apt/sources.list
deb http://archive.ubuntu.com/ubuntu bionic main multiverse restricted universe
deb http://archive.ubuntu.com/ubuntu bionic-security main multiverse restricted universe
deb http://archive.ubuntu.com/ubuntu bionic-updates main multiverse restricted universe
deb [arch=amd64] http://nginx.org/packages/mainline/ubuntu/ bionic nginx
deb [arch=amd64] http://mirror2.hs-esslingen.de/mariadb/repo/10.3/ubuntu bionic main
deb http://ppa.launchpad.net/ondrej/php/ubuntu bionic main
EOF
wget http://nginx.org/keys/nginx_signing.key && apt-key add nginx_signing.key
apt-key adv --recv-keys --keyserver hkp://keyserver.ubuntu.com:80 4F4EA0AAE5267A6C
apt-key adv --recv-keys --keyserver hkp://keyserver.ubuntu.com:80 0xF1656F24C74CD1D8
apt update && apt upgrade -y && apt install software-properties-common zip unzip screen curl ffmpeg libfile-fcntllock-perl -y
add-apt-repository ppa:certbot/certbot -y && apt update && apt upgrade -y && apt install letsencrypt ssl-cert -y
apt remove nginx nginx-common nginx-full -y --allow-change-held-packages
apt install nginx -y

Modify NGINX:

systemctl enable nginx.service && apt-mark hold nginx

To update NGINX in the future just issue the following statement:

apt-mark unhold nginx && apt upgrade -y && apt-mark hold nginx

Change NGINX configuration:

mv /etc/nginx/nginx.conf /etc/nginx/nginx.conf.bak && vi /etc/nginx/nginx.conf

to:

user www-data;
worker_processes auto;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
multi_accept on;
use epoll;
}
http {
server_names_hash_bucket_size 64;
upstream php-handler {
server unix:/run/php/php7.3-fpm.sock;
}
set_real_ip_from 127.0.0.1;
set_real_ip_from 192.168.2.0/24;
real_ip_header X-Forwarded-For;
real_ip_recursive on;
include /etc/nginx/mime.types;
#include /etc/nginx/proxy.conf;
#include /etc/nginx/ssl.conf;
#include /etc/nginx/header.conf;
#include /etc/nginx/optimization.conf;
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" '
'"$host" sn="$server_name" '
'rt=$request_time '
'ua="$upstream_addr" us="$upstream_status" '
'ut="$upstream_response_time" ul="$upstream_response_length" '
'cs=$upstream_cache_status' ;
access_log /var/log/nginx/access.log main;
sendfile on;
send_timeout 3600;
tcp_nopush on;
tcp_nodelay on;
open_file_cache max=500 inactive=10m;
open_file_cache_errors on;
keepalive_timeout 65;
reset_timedout_connection on;
server_tokens off;
resolver 208.67.222.222 208.67.220.220 valid=30s;
resolver_timeout 5s;
include /etc/nginx/conf.d/*.conf;
}

Start NGINX:

service nginx restart

Create folders and apply permissions:

mkdir -p /var/nc_data /var/www/letsencrypt /usr/local/tmp/cache /usr/local/tmp/sessions /usr/local/tmp/apc /upload_tmp
chown -R www-data:www-data /upload_tmp /var/nc_data /var/www
chown -R www-data:root /usr/local/tmp/sessions /usr/local/tmp/cache /usr/local/tmp/apc

2. Install PHP

apt install php7.3-fpm php7.3-gd php7.3-mysql php7.3-curl php7.3-xml php7.3-zip php7.3-intl php7.3-mbstring php7.3-json php7.3-bz2 php7.3-ldap php-apcu imagemagick php-imagick php-smbclient -y

Awesome, PHP 7.3 is already installed. Verify your timezone settings

date

and if necessary set it properly

timedatectl set-timezone Europe/Berlin

Configure PHP:

cp /etc/php/7.3/fpm/pool.d/www.conf /etc/php/7.3/fpm/pool.d/www.conf.bak
cp /etc/php/7.3/cli/php.ini /etc/php/7.3/cli/php.ini.bak
cp /etc/php/7.3/fpm/php.ini /etc/php/7.3/fpm/php.ini.bak
cp /etc/php/7.3/fpm/php-fpm.conf /etc/php/7.3/fpm/php-fpm.conf.bak
sed -i "s/;env\[HOSTNAME\] = /env[HOSTNAME] = /" /etc/php/7.3/fpm/pool.d/www.conf
sed -i "s/;env\[TMP\] = /env[TMP] = /" /etc/php/7.3/fpm/pool.d/www.conf
sed -i "s/;env\[TMPDIR\] = /env[TMPDIR] = /" /etc/php/7.3/fpm/pool.d/www.conf
sed -i "s/;env\[TEMP\] = /env[TEMP] = /" /etc/php/7.3/fpm/pool.d/www.conf
sed -i "s/;env\[PATH\] = /env[PATH] = /" /etc/php/7.3/fpm/pool.d/www.conf
sed -i "s/pm.max_children = .*/pm.max_children = 240/" /etc/php/7.3/fpm/pool.d/www.conf
sed -i "s/pm.start_servers = .*/pm.start_servers = 20/" /etc/php/7.3/fpm/pool.d/www.conf
sed -i "s/pm.min_spare_servers = .*/pm.min_spare_servers = 10/" /etc/php/7.3/fpm/pool.d/www.conf
sed -i "s/pm.max_spare_servers = .*/pm.max_spare_servers = 20/" /etc/php/7.3/fpm/pool.d/www.conf
sed -i "s/;pm.max_requests = 500/pm.max_requests = 500/" /etc/php/7.3/fpm/pool.d/www.conf
sed -i "s/output_buffering =.*/output_buffering = 'Off'/" /etc/php/7.3/cli/php.ini
sed -i "s/max_execution_time =.*/max_execution_time = 1800/" /etc/php/7.3/cli/php.ini
sed -i "s/max_input_time =.*/max_input_time = 3600/" /etc/php/7.3/cli/php.ini
sed -i "s/post_max_size =.*/post_max_size = 10240M/" /etc/php/7.3/cli/php.ini
sed -i "s/;upload_tmp_dir =.*/upload_tmp_dir = \/upload_tmp/" /etc/php/7.3/cli/php.ini
sed -i "s/upload_max_filesize =.*/upload_max_filesize = 10240M/" /etc/php/7.3/cli/php.ini
sed -i "s/max_file_uploads =.*/max_file_uploads = 100/" /etc/php/7.3/cli/php.ini
sed -i "s/;date.timezone.*/date.timezone = Europe\/\Berlin/" /etc/php/7.3/cli/php.ini
sed -i "s/;session.cookie_secure.*/session.cookie_secure = True/" /etc/php/7.3/cli/php.ini
sed -i "s/;session.save_path =.*/session.save_path = \"N;700;\/usr\/local\/tmp\/sessions\"/" /etc/php/7.3/cli/php.ini
sed -i '$aapc.enable_cli = 1' /etc/php/7.3/cli/php.ini
sed -i "s/memory_limit = 128M/memory_limit = 512M/" /etc/php/7.3/fpm/php.ini
sed -i "s/output_buffering =.*/output_buffering = 'Off'/" /etc/php/7.3/fpm/php.ini
sed -i "s/max_execution_time =.*/max_execution_time = 1800/" /etc/php/7.3/fpm/php.ini
sed -i "s/max_input_time =.*/max_input_time = 3600/" /etc/php/7.3/fpm/php.ini
sed -i "s/post_max_size =.*/post_max_size = 10240M/" /etc/php/7.3/fpm/php.ini
sed -i "s/;upload_tmp_dir =.*/upload_tmp_dir = \/upload_tmp/" /etc/php/7.3/fpm/php.ini
sed -i "s/upload_max_filesize =.*/upload_max_filesize = 10240M/" /etc/php/7.3/fpm/php.ini
sed -i "s/max_file_uploads =.*/max_file_uploads = 100/" /etc/php/7.3/fpm/php.ini
sed -i "s/;date.timezone.*/date.timezone = Europe\/\Berlin/" /etc/php/7.3/fpm/php.ini
sed -i "s/;session.cookie_secure.*/session.cookie_secure = True/" /etc/php/7.3/fpm/php.ini
sed -i "s/;opcache.enable=.*/opcache.enable=1/" /etc/php/7.3/fpm/php.ini
sed -i "s/;opcache.enable_cli=.*/opcache.enable_cli=1/" /etc/php/7.3/fpm/php.ini
sed -i "s/;opcache.memory_consumption=.*/opcache.memory_consumption=128/" /etc/php/7.3/fpm/php.ini
sed -i "s/;opcache.interned_strings_buffer=.*/opcache.interned_strings_buffer=8/" /etc/php/7.3/fpm/php.ini
sed -i "s/;opcache.max_accelerated_files=.*/opcache.max_accelerated_files=10000/" /etc/php/7.3/fpm/php.ini
sed -i "s/;opcache.revalidate_freq=.*/opcache.revalidate_freq=1/" /etc/php/7.3/fpm/php.ini
sed -i "s/;opcache.save_comments=.*/opcache.save_comments=1/" /etc/php/7.3/fpm/php.ini
sed -i "s/;session.save_path =.*/session.save_path = \"N;700;\/usr\/local\/tmp\/sessions\"/" /etc/php/7.3/fpm/php.ini
sed -i "s/;emergency_restart_threshold =.*/emergency_restart_threshold = 10/" /etc/php/7.3/fpm/php-fpm.conf
sed -i "s/;emergency_restart_interval =.*/emergency_restart_interval = 1m/" /etc/php/7.3/fpm/php-fpm.conf
sed -i "s/;process_control_timeout =.*/process_control_timeout = 10s/" /etc/php/7.3/fpm/php-fpm.conf
sed -i '$aapc.enabled=1' /etc/php/7.3/fpm/php.ini
sed -i '$aapc.file_update_protection=2' /etc/php/7.3/fpm/php.ini
sed -i '$aapc.optimization=0' /etc/php/7.3/fpm/php.ini
sed -i '$aapc.shm_size=256M' /etc/php/7.3/fpm/php.ini
sed -i '$aapc.include_once_override=0' /etc/php/7.3/fpm/php.ini
sed -i '$aapc.shm_segments=1' /etc/php/7.3/fpm/php.ini
sed -i '$aapc.ttl=7200' /etc/php/7.3/fpm/php.ini
sed -i '$aapc.user_ttl=7200' /etc/php/7.3/fpm/php.ini
sed -i '$aapc.gc_ttl=3600' /etc/php/7.3/fpm/php.ini
sed -i '$aapc.num_files_hint=1024' /etc/php/7.3/fpm/php.ini
sed -i '$aapc.enable_cli=0' /etc/php/7.3/fpm/php.ini
sed -i '$aapc.max_file_size=5M' /etc/php/7.3/fpm/php.ini
sed -i '$aapc.cache_by_default=1' /etc/php/7.3/fpm/php.ini
sed -i '$aapc.use_request_time=1' /etc/php/7.3/fpm/php.ini
sed -i '$aapc.slam_defense=0' /etc/php/7.3/fpm/php.ini
sed -i '$aapc.mmap_file_mask=/usr/local/tmp/apc/apc.XXXXXX' /etc/php/7.3/fpm/php.ini
sed -i '$aapc.stat_ctime=0' /etc/php/7.3/fpm/php.ini
sed -i '$aapc.canonicalize=1' /etc/php/7.3/fpm/php.ini
sed -i '$aapc.write_lock=1' /etc/php/7.3/fpm/php.ini
sed -i '$aapc.report_autofilter=0' /etc/php/7.3/fpm/php.ini
sed -i '$aapc.rfc1867=0' /etc/php/7.3/fpm/php.ini
sed -i '$aapc.rfc1867_prefix =upload_' /etc/php/7.3/fpm/php.ini
sed -i '$aapc.rfc1867_name=APC_UPLOAD_PROGRESS' /etc/php/7.3/fpm/php.ini
sed -i '$aapc.rfc1867_freq=0' /etc/php/7.3/fpm/php.ini
sed -i '$aapc.rfc1867_ttl=3600' /etc/php/7.3/fpm/php.ini
sed -i '$aapc.lazy_classes=0' /etc/php/7.3/fpm/php.ini
sed -i '$aapc.lazy_functions=0' /etc/php/7.3/fpm/php.ini
sed -i "s/09,39.*/# &/" /etc/cron.d/php
(crontab -l ; echo "09,39 * * * * /usr/lib/php/sessionclean 2>&1") | crontab -u root -

Modify /etc/fstab

Determine the uid of your www-data user by issuing

id www-data

and only if it differs from ‘uid=33‘ replace the ‘uid=33‘ in the following rows properly before executing them!

sed -i '$atmpfs /usr/local/tmp/apc tmpfs defaults,uid=33,size=300M,noatime,nosuid,nodev,noexec,mode=1777 0 0' /etc/fstab
sed -i '$atmpfs /usr/local/tmp/cache tmpfs defaults,uid=33,size=300M,noatime,nosuid,nodev,noexec,mode=1777 0 0' /etc/fstab
sed -i '$atmpfs /usr/local/tmp/sessions tmpfs defaults,uid=33,size=300M,noatime,nosuid,nodev,noexec,mode=1777 0 0' /etc/fstab

OPTIONAL:

sed -i '$atmpfs /tmp tmpfs defaults,noatime,nosuid,nodev,noexec,mode=1777 0 0' /etc/fstab
sed -i '$atmpfs /var/tmp tmpfs defaults,noatime,nosuid,nodev,noexec,mode=1777 0 0' /etc/fstab

Mount tmpfs and then restart both, PHP and NGINX:

mount -a && service php7.3-fpm restart && service nginx restart

3. MariaDB

If you are interested in Postgresql instead of MariaDB please have a look here. Update your system and install MariaDB:

apt update && apt install mariadb-server -y

Verify your database server version:

mysql --version

A version like …

mysql Ver 15.1 Distrib 10.3.12-MariaDB, for debian-linux-gnu (x86_64) using readline 5.2

10.3.12-MariaDB… should appear.

Secure MariaDB:

mysql_secure_installation
Enter current password for root (enter for none): <ENTER> or type the password
Set root password? [Y/n] Y

If already set during the MariaDB installation you will be asked wether to change or keep the 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

Configure MariaDB:

service mysql stop
mv /etc/mysql/my.cnf /etc/mysql/my.cnf.bak && vi /etc/mysql/my.cnf

Paste the following rows:

[client]
port = 3306
socket = /var/run/mysqld/mysqld.sock
default-character-set = utf8mb4
[mysqld_safe]
log_error=/var/log/mysql/mysql_error.log
socket = /var/run/mysqld/mysqld.sock
nice = 0
[mysqld]
user = mysql
pid-file = /var/run/mysqld/mysqld.pid
log_error=/var/log/mysql/mysql_error.log
general_log_file = /var/log/mysql/mysql.log
general_log = 0
socket = /var/run/mysqld/mysqld.sock
port = 3306
basedir = /usr
datadir = /var/lib/mysql
tmpdir = /tmp
lc_messages_dir = /usr/share/mysql
lc_messages = en_US
skip-external-locking
skip-name-resolve
bind-address = 127.0.0.1
max_connections = 200
connect_timeout = 5
wait_timeout = 600
max_allowed_packet = 16M
thread_cache_size = 128
sort_buffer_size = 4M
bulk_insert_buffer_size = 16M
tmp_table_size = 64M
max_heap_table_size = 64M
myisam_recover_options = BACKUP
key_buffer_size = 128M
#open-files-limit = 2000
table_open_cache = 400
myisam_sort_buffer_size = 512M
concurrent_insert = 2
read_buffer_size = 2M
read_rnd_buffer_size = 1M
query_cache_limit = 2M
query_cache_size = 64M
query_cache_type = 1
query_cache_min_res_unit = 2k
log_warnings = 2
slow_query_log_file = /var/log/mysql/mariadb-slow.log
long_query_time = 1
log_slow_verbosity = query_plan
slow-query-log = 1
slow-query-log-file = /var/log/mysql/slow.log
log_bin = /var/log/mysql/mariadb-bin
log_bin_index = /var/log/mysql/mariadb-bin.index
expire_logs_days = 10
max_binlog_size = 100M
default_storage_engine = InnoDB
innodb_buffer_pool_size = 1024M
innodb_buffer_pool_instances = 1
innodb_flush_log_at_trx_commit = 2
innodb_log_buffer_size = 32M
innodb_max_dirty_pages_pct = 90
innodb_file_per_table = 1
innodb_open_files = 400
innodb_io_capacity = 4000
innodb_flush_method = O_DIRECT
character-set-server = utf8mb4
collation-server = utf8mb4_general_ci
transaction_isolation = READ-COMMITTED
binlog_format = ROW
[mysqldump]
quick
quote-names
max_allowed_packet = 16M
[mysql]
#no-auto-rehash    # faster start of mysql but no tab completion
[isamchk]
key_buffer = 16M
!include /etc/mysql/mariadb.cnf
!includedir /etc/mysql/conf.d/

Restart MariaDB:

service mysql restart

Create the database and the user:

mysql -h localhost -uroot -p -e "CREATE DATABASE nextcloud CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; CREATE USER nextcloud@localhost identified by 'nextcloud'; GRANT ALL PRIVILEGES on nextcloud.* to nextcloud@localhost; FLUSH privileges;"

Verify the transaction Isolation level was set to READ_Commit and the collation was set to UTF8MB4 properly:

mysql -h localhost -uroot -p -e "SELECT @@TX_ISOLATION; SELECT SCHEMA_NAME 'database', default_character_set_name 'charset', DEFAULT_COLLATION_NAME 'collation' FROM information_schema.SCHEMATA WHERE SCHEMA_NAME='nextcloud'"

If the resultset will be “READ-COMMITTED” and “utf8mb4_general_ci” as shown go ahead with the installation of redis.


4. Redis

apt update && apt install redis-server php-redis -y

Change configuration and group membership:

cp /etc/redis/redis.conf /etc/redis/redis.conf.bak
sed -i "s/port 6379/port 0/" /etc/redis/redis.conf
sed -i s/\#\ unixsocket/\unixsocket/g /etc/redis/redis.conf
sed -i "s/unixsocketperm 700/unixsocketperm 770/" /etc/redis/redis.conf 
sed -i "s/# maxclients 10000/maxclients 512/" /etc/redis/redis.conf
usermod -a -G redis www-data
cp /etc/sysctl.conf /etc/sysctl.conf.bak && sed -i '$avm.overcommit_memory = 1' /etc/sysctl.conf

Reboot your server:

shutdown -r now

5. Create the nextcloud.conf:

sudo -s
mv /etc/nginx/conf.d/default.conf /etc/nginx/conf.d/default.conf.bak && touch /etc/nginx/conf.d/default.conf && vi /etc/nginx/conf.d/nextcloud.conf

Paste the following rows:

server {
server_name YOUR.DEDYN.IO;
listen 80 default_server;
location ^~ /.well-known/acme-challenge {
proxy_pass http://127.0.0.1:81;
proxy_set_header Host $host;
}
location / {
return 301 https://$host$request_uri;
}
}
server {
server_name YOUR.DEDYN.IO;
listen 443 ssl http2 default_server;
root /var/www/nextcloud/;
access_log /var/log/nginx/nextcloud.access.log main;
error_log /var/log/nginx/nextcloud.error.log warn;
location = /robots.txt {
allow all;
log_not_found off;
access_log off;
}
location = /.well-known/carddav {
return 301 $scheme://$host/remote.php/dav;
}
location = /.well-known/caldav {
return 301 $scheme://$host/remote.php/dav;
}
#SOCIAL app enabled? Please uncomment the following three rows
#rewrite ^/.well-known/webfinger /public.php?service=webfinger last;
#rewrite ^/.well-known/host-meta /public.php?service=host-meta last;
#rewrite ^/.well-known/host-meta.json /public.php?service=host-meta-json last;
client_max_body_size 10240M;
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 ~ \.(?:flv|mp4|mov|m4a)$ {
mp4;
mp4_buffer_size 100M;
mp4_max_buffer_size 1024M;
fastcgi_split_path_info ^(.+\.php)(/.*)$;
include fastcgi_params;
include php_optimization.conf;
fastcgi_pass php-handler;
fastcgi_param HTTPS on;
}
location ~ ^/(?:index|remote|public|cron|core/ajax/update|status|ocs/v[12]|updater/.+|ocs-provider/.+)\.php(?:$|/) {
fastcgi_split_path_info ^(.+\.php)(/.*)$;
include fastcgi_params;
include php_optimization.conf;
fastcgi_pass php-handler;
fastcgi_param HTTPS on;
}
location ~ ^/(?:updater|ocs-provider)(?:$|/) {
try_files $uri/ =404;
index index.php;
}
location ~ \.(?:css|js|woff2?|svg|gif|png|html|ttf|ico|jpg|jpeg)$ {
try_files $uri /index.php$uri$is_args$args;
access_log off;
expires 360d;
}
}

If you want your Nextcloud running in a subdir like https://your.dedyn.io/nextcloud use this nextcloud.conf instead:

server {
server_name your.dedyn.io;
listen 80 default_server;
location ^~ /.well-known/acme-challenge {
proxy_pass http://127.0.0.1:81;
proxy_set_header Host $host;
}
location / {
return 301 https://$host$request_uri;
}
}
server {
server_name your.dedyn.io;
listen 443 ssl http2 default_server;
root /var/www/;
access_log /var/log/nginx/nextcloud.access.log main;
error_log /var/log/nginx/nextcloud.error.log warn;
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;
}
#SOCIAL app enabled? Please uncomment the following three rows
#rewrite ^/.well-known/webfinger /nextcloud/public.php?service=webfinger last;
#rewrite ^/.well-known/host-meta /nextcloud/public.php?service=host-meta last;
#rewrite ^/.well-known/host-meta.json /nextcloud/public.php?service=host-meta-json last;
client_max_body_size 10240M;
location ^~ /nextcloud {
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 ~ \.(?:flv|mp4|mov|m4a)$ {
mp4;
mp4_buffer_size 100M;
mp4_max_buffer_size 1024M;
fastcgi_split_path_info ^(.+\.php)(/.*)$;
include fastcgi_params;
include php_optimization.conf;
fastcgi_pass php-handler;
fastcgi_param HTTPS on;
}
location ~ ^/nextcloud/(?:index|remote|public|cron|core/ajax/update|status|ocs/v[12]|updater/.+|ocs-provider/.+)\.php(?:$|/) {
fastcgi_split_path_info ^(.+\.php)(/.*)$;
include fastcgi_params;
include php_optimization.conf;
fastcgi_pass php-handler;
fastcgi_param HTTPS on;
}
location ~ ^/nextcloud/(?:updater|ocs-provider)(?:$|/) {
try_files $uri/ =404;
index index.php;
}
location ~ \.(?:png|html|ttf|ico|jpg|jpeg|css|js|woff2?|svg|gif)$ {
try_files $uri /nextcloud/index.php$uri$is_args$args;
access_log off;
expires 360d;
}
}
}

Create the letsencrypt.conf:

vi /etc/nginx/conf.d/letsencrypt.conf

Paste the following rows:

server {
server_name 127.0.0.1;
listen 127.0.0.1:81 default_server;
charset utf-8;
access_log /var/log/nginx/le.access.log main;
error_log /var/log/nginx/le.error.log warn;
location ^~ /.well-known/acme-challenge {
default_type text/plain;
root /var/www/letsencrypt;
}
}

Create the ssl.conf:

vi /etc/nginx/ssl.conf

Paste the following rows:

ssl_certificate /etc/ssl/certs/ssl-cert-snakeoil.pem;
ssl_certificate_key /etc/ssl/private/ssl-cert-snakeoil.key;
ssl_trusted_certificate /etc/ssl/certs/ssl-cert-snakeoil.pem;
#ssl_certificate /etc/letsencrypt/live/YOUR.DEDYN.IO/fullchain.pem;
#ssl_certificate_key /etc/letsencrypt/live/YOUR.DEDYN.IO/privkey.pem;
#ssl_trusted_certificate /etc/letsencrypt/live/YOUR.DEDYN.IO/chain.pem;
ssl_dhparam /etc/ssl/certs/dhparam.pem;
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:50m;
ssl_session_tickets off;
ssl_protocols TLSv1.2;
ssl_ciphers 'ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384';
ssl_ecdh_curve secp521r1:secp384r1:prime256v1;
ssl_prefer_server_ciphers on;
ssl_stapling on;
ssl_stapling_verify on;

OPTIONAL (If you compiled NGINX 1.15.8 with OpenSSL 1.1.1) add

ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers 'TLS-CHACHA20-POLY1305-SHA256:TLS-AES-256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384';
ssl_early_data on;

Create the proxy.conf

vi /etc/nginx/proxy.conf

Paste the following rows:

proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Protocol $scheme;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-Forwarded-Port $server_port;
proxy_set_header X-Forwarded-Server $host;
proxy_connect_timeout 3600;
proxy_send_timeout 3600;
proxy_read_timeout 3600;
proxy_redirect off;

OPTIONAL (If you compiled NGINX 1.15.8 with OpenSSL 1.1.1) add:

proxy_set_header Early-Data $ssl_early_data;

Create the header.conf:

vi /etc/nginx/header.conf

Paste the following rows:

add_header Strict-Transport-Security "max-age=15768000; includeSubDomains; preload;";
add_header X-Robots-Tag none;
add_header X-Download-Options noopen;
add_header X-Permitted-Cross-Domain-Policies none;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "no-referrer" always;
add_header Feature-Policy "accelerometer 'none'; autoplay 'self'; geolocation 'none'; midi 'none'; notifications 'self'; push 'self'; sync-xhr 'self' https://your.dedyn.io; microphone 'self'; camera 'self'; magnetometer 'none'; gyroscope 'none'; speaker 'self'; vibrate 'self'; fullscreen 'self'; payment 'none'; usb 'none'";

Create the optimization.conf:

vi /etc/nginx/optimization.conf

Paste the following rows:

fastcgi_read_timeout 3600;
fastcgi_buffers 64 64K;
fastcgi_buffer_size 256k;
fastcgi_busy_buffers_size 3840K;
fastcgi_cache_key $http_cookie$request_method$host$request_uri;
fastcgi_cache_use_stale error timeout invalid_header http_500;
fastcgi_ignore_headers Cache-Control Expires Set-Cookie;
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;
gzip_disable "MSIE [1-6]\.";

Create the php_optimization.conf:

vi /etc/nginx/php_optimization.conf

Paste the following rows:

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_intercept_errors on;
fastcgi_request_buffering off;
fastcgi_cache_valid 404 1m;
fastcgi_cache_valid any 1h;
fastcgi_cache_methods GET HEAD;

Enhance security:

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

To leave screen press STRG+A following by ‘d’ – to resume run screen -r. Please be patient, it will take a while.

Restart NGINX:

sed -i s/\#\include/\include/g /etc/nginx/nginx.conf && service nginx restart

Download and extract Nextcloud:

cd /usr/local/src
wget https://download.nextcloud.com/server/releases/latest.tar.bz2 && tar -xjf latest.tar.bz2 -C /var/www && chown -R www-data:www-data /var/www/ && rm latest.tar.bz2

Request your ssl-certificate(s):

letsencrypt certonly -a webroot --webroot-path=/var/www/letsencrypt --rsa-key-size 4096 -d YOUR.DEDYN.IO

Apply the permissions using a permissions.sh script:

vi /root/permissions.sh

Paste the following rows:

#!/bin/bash
find /var/www/ -type f -print0 | xargs -0 chmod 0640
find /var/www/ -type d -print0 | xargs -0 chmod 0750
chown -R www-data:www-data /var/www/
chown -R www-data:www-data /upload_tmp/
chown -R www-data:www-data /var/nc_data/
chmod 0644 /var/www/nextcloud/.htaccess
chmod 0644 /var/www/nextcloud/.user.ini
chmod 600 /etc/letsencrypt/live/YOUR.DEDYN.IO/fullchain.pem
chmod 600 /etc/letsencrypt/live/YOUR.DEDYN.IO/privkey.pem
chmod 600 /etc/letsencrypt/live/YOUR.DEDYN.IO/chain.pem
chmod 600 /etc/letsencrypt/live/YOUR.DEDYN.IO/cert.pem
chmod 600 /etc/ssl/certs/dhparam.pem
exit 0

Run the script:

chmod +x /root/permissions.sh && /root/permissions.sh

Modify the ssl.conf and restart NGINX:

sed -i '/ssl-cert-snakeoil/d' /etc/nginx/ssl.conf
sed -i s/\#\ssl/\ssl/g /etc/nginx/ssl.conf
service nginx restart

Create a certificate renewal automatism:

sed -i "s/SHELL=*/# &/" /etc/cron.d/certbot
sed -i "s/PATH=*/# &/" /etc/cron.d/certbot
sed -i "s/0 =*/# &/" /etc/cron.d/certbot
vi /root/renewal.sh

Paste the following rows

#!/bin/bash
cd /etc/letsencrypt
letsencrypt renew
result=$(find /etc/letsencrypt/live/ -type l -mtime -1 )
if [ -n "$result" ]; then
/usr/sbin/service nginx stop
/usr/sbin/service mysql restart
/usr/sbin/service redis-server restart
/usr/sbin/service php7.3-fpm restart
/usr/sbin/service nginx restart
fi
exit 0

Make it exectuable and create a cronjob

chmod +x /root/renewal.sh && crontab -e

Paste the red row below existing ones:

09,39 * * * * /usr/lib/php/sessionclean 2>&1
@monthly /root/renewal.sh 2>&1

Install Nextcloud silently

sudo -u www-data php /var/www/nextcloud/occ maintenance:install --database "mysql" --database-name "nextcloud" --database-user "nextcloud" --database-pass "nextcloud" --admin-user "YourNextcloudAdmin" --admin-pass "YourNextcloudAdminPasssword" --data-dir "/var/nc_data"

Information:

–database-user “nextcloud” : As set above while creating the database and user

–database-pass “nextcloud” : As set above while creating the database and user

–admin-user “YourNextcloudAdmin” : your free choice

–admin-pass “YourNextcloudAdminPasssword” : your free choice

Finish the installation, then make ammendments to your config.php as www-data:

sudo -u www-data php /var/www/nextcloud/occ config:system:set trusted_domains 1 --value=your.dedyn.io
sudo -u www-data php /var/www/nextcloud/occ config:system:set overwrite.cli.url --value=https://your.dedyn.io
sudo -u www-data cp /var/www/nextcloud/config/config.php /var/www/nextcloud/config/config.php.bak

Expand your Nextcloud config.php:

sudo -u www-data sed -i 's/^[ ]*//' /var/www/nextcloud/config/config.php
sudo -u www-data sed -i '/);/d' /var/www/nextcloud/config/config.php
sudo -u www-data cat <<EOF >>/var/www/nextcloud/config/config.php
'activity_expire_days' => 14,
'auth.bruteforce.protection.enabled' => true,
'blacklisted_files' => 
array (
0 => '.htaccess',
1 => 'Thumbs.db',
2 => 'thumbs.db',
),
'cron_log' => true,
'enable_previews' => true,
'enabledPreviewProviders' => 
array (
0 => 'OC\\Preview\\PNG',
1 => 'OC\\Preview\\JPEG',
2 => 'OC\\Preview\\GIF',
3 => 'OC\\Preview\\BMP',
4 => 'OC\\Preview\\XBitmap',
5 => 'OC\\Preview\\Movie',
6 => 'OC\\Preview\\PDF',
7 => 'OC\\Preview\\MP3',
8 => 'OC\\Preview\\TXT',
9 => 'OC\\Preview\\MarkDown',
),
'filesystem_check_changes' => 0,
'filelocking.enabled' => 'true',
'htaccess.RewriteBase' => '/',
'integrity.check.disabled' => false,
'knowledgebaseenabled' => false,
'logfile' => '/var/nc_data/nextcloud.log',
'loglevel' => 2,
'logtimezone' => 'Europe/Berlin',
'log_rotate_size' => 104857600,
'maintenance' => false,
'memcache.local' => '\\OC\\Memcache\\APCu',
'memcache.locking' => '\\OC\\Memcache\\Redis',
'overwriteprotocol' => 'https',
'preview_max_x' => 1024,
'preview_max_y' => 768,
'preview_max_scale_factor' => 1,
'redis' => 
array (
'host' => '/var/run/redis/redis-server.sock',
'port' => 0,
'timeout' => 0.0,
),
'quota_include_external_storage' => false,
'share_folder' => '/Shares',
'skeletondirectory' => '',
'theme' => '',
'trashbin_retention_obligation' => 'auto, 7',
'updater.release.channel' => 'stable',
);
EOF

Edit the .user.ini:

sudo -u www-data sed -i "s/upload_max_filesize=.*/upload_max_filesize=10240M/" /var/www/nextcloud/.user.ini
sudo -u www-data sed -i "s/post_max_size=.*/post_max_size=10240M/" /var/www/nextcloud/.user.ini
sudo -u www-data sed -i "s/output_buffering=.*/output_buffering='Off'/" /var/www/nextcloud/.user.ini
service php7.3-fpm restart && service redis-server restart && service nginx restart

Adjust Nextcloud

sudo -u www-data php /var/www/nextcloud/occ config:system:set 'auth.bruteforce.protection.enabled' --value=false
sudo -u www-data php /var/www/nextcloud/occ app:disable survey_client
sudo -u www-data php /var/www/nextcloud/occ app:disable firstrunwizard
sudo -u www-data php /var/www/nextcloud/occ app:enable admin_audit
sudo -u www-data php /var/www/nextcloud/occ app:enable files_pdfviewer

Logon to your brandly new Nextcloud in your browser

https://your.dedyn.io/login

If the integrity check within Nextcloud will fail, try to change the config.php

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

and set :

'integrity.check.disabled' => true,

Then restart all services:

service php7.3-fpm restart && service redis-server restart && service nginx restart

Re-run the integrity check and set the value back to ‘false’:

sudo -u www-data vi /var/www/nextcloud/config/config.php
'integrity.check.disabled' => false,

Restart all services again.

service php7.3-fpm restart && service redis-server restart && service nginx restart

and the message should disappear!


Optimize your Nextcloud once (a) and regulary (b) using a script

(a)

/usr/sbin/service nginx stop
sudo -u www-data php /var/www/nextcloud/occ db:add-missing-indices
sudo -u www-data php /var/www/nextcloud/occ db:convert-filecache-bigint
/usr/sbin/service nginx start

(infos: BigInt, missing indices)

(b)

vi /root/optimize.sh
#!/bin/bash
redis-cli -s /var/run/redis/redis-server.sock <<EOF
FLUSHALL
quit
EOF
sudo -u www-data php /var/www/nextcloud/occ files:scan --all
sudo -u www-data php /var/www/nextcloud/occ files:scan-app-data
exit 0

Save the script and mark it as executable

chmod +x /root/optimize.sh

Issue the optimize.sh script initially:

/root/optimize.sh

Add Nextcloud cronjobs for www-data and root

For www-data:

crontab -u www-data -e

Paste the following rows

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

For root:

crontab -e

Paste the follwoing rows:

5 1 * * * /root/optimize.sh > /dev/null 2>&1

Don’t forget to switch from Ajax to Cron in Nextclouds-Adminpanel or use Nextcloud CLI to switch immediately:

sudo -u www-data php /var/www/nextcloud/occ background:cron

Finally verify your server security level

(1)

https://www.ssllabs.com/ssltest/analyze.html?d=your.dedyn.io

(2)

https://scan.nextcloud.com

(3)

https://observatory.mozilla.org/analyze/your.dedyn.io


6. Harden your System using fail2ban and ufw

First install and configure fail2ban and finally configure the firewall ufw to secure and harden Nextcloud.

Install and configure fail2ban:

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

Create the Nextcloud-filter:

vi /etc/fail2ban/filter.d/nextcloud.conf

Paste the following rows to the fail2ban filter for Nextcloud (or download as txt file to avoid WordPress-code-issues!):

[Definition]
failregex=^{"reqId":".*","remoteAddr":".*","app":"core","message":"Login failed: '.*' \(Remote IP: '<HOST>'\)","level":2,"time":".*"}$
            ^{"reqId":".*","level":2,"time":".*","remoteAddr":".*","app":"core".*","message":"Login failed: '.*' \(Remote IP: '<HOST>'\)".*}$
            ^.*\"remoteAddr\":\"<HOST>\".*Trusted domain error.*$

Create a new jail:

vi /etc/fail2ban/jail.d/nextcloud.local

Paste the following rows:

[nextcloud]
backend = auto
enabled = true
port = 80,443
protocol = tcp
filter = nextcloud
maxretry = 3
bantime = 36000
findtime = 36000
logpath = /var/nc_data/nextcloud.log

[nginx-http-auth]
enabled = true

Re-start the fail2ban-service:

service fail2ban restart

Configure your ufw (uncomplicated firewall):

apt install ufw -y && ufw allow 80/tcp && ufw allow 443/tcp && ufw allow 22/tcp

Enable and restart ufw by running

ufw logging medium && ufw default deny incoming && ufw enable && service ufw restart

6.1 Harden your Nextcloud using Spamhaus Project and UFW

If you’d like to prevent “unprivileged visitors” just create the script /root/ufw-spamhaus.sh and block them by ufw directly.

vi /root/ufw-spamhaus.sh

Paste the following rows:

#!/bin/bash
# Thanks to @ank0m
EXEC_DATE=`date +%Y-%m-%d`
SPAMHAUS_DROP="/usr/local/src/drop.txt"
SPAMHAUS_eDROP="/usr/local/src/edrop.txt"
URL="https://www.spamhaus.org/drop/drop.txt"
eURL="https://www.spamhaus.org/drop/edrop.txt"
DROP_ADD_TO_UFW="/usr/local/src/DROP2.txt"
eDROP_ADD_TO_UFW="/usr/local/src/eDROP2.txt"
DROP_ARCHIVE_FILE="/usr/local/src/DROP_$EXEC_DATE"
eDROP_ARCHIVE_FILE="/usr/local/src/eDROP_$EXEC_DATE"
# All credits for the following BLACKLISTS goes to "The Spamhaus Project" - https://www.spamhaus.org
echo "Start time: $(date)"
echo " "
echo "Download daily DROP file:"
wget -q -O - "$URL" > $SPAMHAUS_DROP
grep -v '^;' $SPAMHAUS_DROP | cut -d ' ' -f 1 > $DROP_ADD_TO_UFW
echo " "
echo "Extract DROP IP addresses and add to UFW:"
cat $DROP_ADD_TO_UFW | while read line
do
/usr/sbin/ufw insert 1 deny from "$line" comment 'DROP_Blacklisted_IPs'
done
echo " "
echo "Downloading eDROP list and import to UFW"
echo " "
echo "Download daily eDROP file:"
wget -q -O - "$eURL" > $SPAMHAUS_eDROP
grep -v '^;' $SPAMHAUS_eDROP | cut -d ' ' -f 1 > $eDROP_ADD_TO_UFW
echo " "
echo "Extract eDROP IP addresses and add to UFW:"
cat $eDROP_ADD_TO_UFW | while read line
do
/usr/sbin/ufw insert 1 deny from "$line" comment 'eDROP_Blacklisted_IPs'
done
echo " "
#####
## To remove or revert these rules, keep the list of IPs!
## Run a command like so to remove the rules:
# while read line; do ufw delete deny from $line; done < $ARCHIVE_FILE
#####
echo "Backup DROP IP address list:"
mv $DROP_ADD_TO_UFW $DROP_ARCHIVE_FILE
echo " "
echo "Backup eDROP IP address list:"
mv $eDROP_ADD_TO_UFW $eDROP_ARCHIVE_FILE
echo " "
echo End time: $(date)

Make the script exutable by issuing

chmod +x /root/ufw-spamhaus.sh

and configure it in your crontab to be issued automatically.

(crontab -l ; echo "10 2 * * * /root/ufw-spamhaus.sh 2>&1") | crontab -u root -

Finally perform an initial run

/root/ufw-spamhaus.sh

and many UFW rules will be applied immediately. Be patient, it may take a while.


Monitor your entire system using netdata

Start download netdata – the directory ‘netdata’ will be created

apt install apache2-utils git gcc make autoconf automake pkg-config uuid-dev zlib1g-dev
cd /usr/local/src
git clone https://github.com/firehol/netdata.git --depth=1
cd netdata

Create a passwordfile to protect netdata:

htpasswd -c /etc/nginx/netdata-access YourName

Then run the script netdata-installer.sh with root privileges to build, install and start netdata

./netdata-installer.sh

Netdata is already installed. We will make smaller adjustementss to netdata’s configuration:

vi /etc/netdata/netdata.conf

First we change the value for “history” to e.g. 14400 (4 hours of chart data retention, uses about 60 MB of RAM) in the [global] section:

 history = 14400

Then we change the binding in the [web] section to localhost (127.0.0.1) only:

 bind to = 127.0.0.1

Finally we enhance the nextcloud.conf and nginx.conf file to include the netdata webserver-configuration:

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

Paste the red rows as shown below to the nextcloud.conf:

...
location / {
 rewrite ^ /index.php$uri;
 }
location /netdata {
 return 301 /netdata/;
 }
 location ~ /netdata/(?<ndpath>.*) {
 auth_basic "Restricted Area";
 auth_basic_user_file /etc/nginx/netdata-access;
 proxy_http_version 1.1;
 proxy_pass_request_headers on;
 proxy_set_header Connection "keep-alive";
 proxy_store off;
 proxy_pass http://netdata/$ndpath$is_args$args;
 gzip on;
 gzip_proxied any;
 gzip_types *;
 }
 location ~ ^/(?:build|tests|config|lib|3rdparty|templates|data)/ {
 deny all;
...

Your entire nextcloud.conf should look like:

server {
server_name your.dedyn.io;
listen 80 default_server;
location ^~ /.well-known/acme-challenge {
proxy_pass http://127.0.0.1:81;
proxy_set_header Host $host;
}
location / {
return 301 https://$host$request_uri;
}
}
server {
server_name your.dedyn.io;
listen 443 ssl http2 default_server;
root /var/www/nextcloud/;
access_log /var/log/nginx/nextcloud.access.log main;
error_log /var/log/nginx/nextcloud.error.log warn;
location = /robots.txt {
allow all;
log_not_found off;
access_log off;
}
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 10240M;
location / {
rewrite ^ /index.php$uri;
}
location /netdata {
return 301 /netdata/;
}
location ~ /netdata/(?<ndpath>.*) {
auth_basic "Restricted Area";
auth_basic_user_file /etc/nginx/netdata-access;
proxy_http_version 1.1;
proxy_pass_request_headers on;
proxy_set_header Connection "keep-alive";
proxy_store off;
proxy_pass http://netdata/$ndpath$is_args$args;
gzip on;
gzip_proxied any;
gzip_types *;
}
location ~ ^/(?:build|tests|config|lib|3rdparty|templates|data)/ {
deny all;
}
location ~ ^/(?:\.|autotest|occ|issue|indie|db_|console) {
deny all;
}
location ~ \.(?:flv|mp4|mov|m4a)$ {
mp4;
mp4_buffer_size 100M;
mp4_max_buffer_size 1024M;
fastcgi_split_path_info ^(.+\.php)(/.*)$;
include fastcgi_params;
include php_optimization.conf;
fastcgi_pass php-handler;
fastcgi_param HTTPS on;
}
location ~ ^/(?:index|remote|public|cron|core/ajax/update|status|ocs/v[12]|updater/.+|ocs-provider/.+)\.php(?:$|/) {
fastcgi_split_path_info ^(.+\.php)(/.*)$;
include fastcgi_params;
include php_optimization.conf;
fastcgi_pass php-handler;
fastcgi_param HTTPS on;
}
location ~ ^/(?:updater|ocs-provider)(?:$|/) {
try_files $uri/ =404;
index index.php;
}
location ~ \.(?:css|js|woff2?|svg|gif|png|html|ttf|ico|jpg|jpeg)$ {
try_files $uri /index.php$uri$is_args$args;
access_log off;
expires 360d;
}
}

Create the new /etc/nginx/conf.d/stub_status.conf:

vi /etc/nginx/conf.d/stub_status.conf

Paste all the following rows:

server {
listen 127.0.0.1:80 default_server;
server_name 127.0.0.1;
location /stub_status {
stub_status on;
allow 127.0.0.1;
deny all;
}
}

Save and quit the file (:wq!) and modify the file /etc/nginx/nginx.conf:

...
http {
 server_names_hash_bucket_size 64;
 upstream php-handler {
 server unix:/run/php/php7.3-fpm.sock;
 }
 upstream netdata {
 server 127.0.0.1:19999;
 keepalive 64;
 }
...

Your nginx.conf should look like:

user www-data;
worker_processes auto;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
multi_accept on;
use epoll;
}
http {
server_names_hash_bucket_size 64;
upstream php-handler {
server unix:/run/php/php7.3-fpm.sock;
}
upstream netdata {
server 127.0.0.1:19999;
keepalive 64;
}
set_real_ip_from 127.0.0.1;
set_real_ip_from 192.168.2.0/24;
real_ip_header X-Forwarded-For;
real_ip_recursive on;
include /etc/nginx/mime.types;
include /etc/nginx/proxy.conf;
include /etc/nginx/ssl.conf;
include /etc/nginx/header.conf;
include /etc/nginx/optimization.conf;
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" '
'"$host" sn="$server_name" '
'rt=$request_time '
'ua="$upstream_addr" us="$upstream_status" '
'ut="$upstream_response_time" ul="$upstream_response_length" '
'cs=$upstream_cache_status' ;
access_log /var/log/nginx/access.log main;
sendfile on;
send_timeout 3600;
tcp_nopush on;
tcp_nodelay on;
open_file_cache max=500 inactive=10m;
open_file_cache_errors on;
keepalive_timeout 65;
reset_timedout_connection on;
server_tokens off;
resolver 208.67.222.222 208.67.220.220 valid=30s;
resolver_timeout 5s;
include /etc/nginx/conf.d/*.conf;
}

Save and quit the file (:wq!) and check NGINX

nginx -t

If no errors appear just restart netdata and nginx

service netdata restart && service nginx restart

and call netdata in your browser

https://your.dedyn.io/netdata

or as an external site in your Nextcloud.


Mount additonal storage to your Nextcloud

(a) …using a NAS

(b) …using an external/additional HDD

You may enhance your Nextcloud with data from your NAS-share or an external hdd.


(a) mount your NAS data to a specific Nextcloud-user

It is really simple to mount a NAS share to your Nextcloud using cifs. First install cifs-utils:

apt install cifs-utils -y

Then store your credentials to a special file (e.g. /root/.smbcredentials)

vi /root/.smbcredentials

Write down your username and password:

username=NASuser
password=NASPassword

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

chmod 400 /root/.smbcredentials

Detect the ID of the webuser (www-data) using the id-command:

id www-data

and keep the id in mind to reuse it in /etc/fstab:

cp /etc/fstab /etc/fstab.bak
vi /etc/fstab

Paste the following to the end of fstab

//<NAS>/<share> /var/nc_data/next/files cifs user,uid=33,rw,iocharset=utf8,suid,credentials=/root/.smbcredentials,file_mode=0770,dir_mode=0770 0 0

Please substitue “//<NAS>/<share>“, next and if neccessary the uid=”33” and then try to mount your NAS manually first:

mount //<NAS>/<share>/

or

mount -a

To unmount your NAS manually run

umount //<NAS>/<share>/

or

umount -a

It will be neccessary to rescan your data for the first usage once. So change to your Nextcloud directory and execute Nextclouds files:scan for the relevant Nextcloud-user (e.g. next) or all (–all):

service nginx stop
cd /var/www/nextcloud
redis-cli -s /var/run/redis/redis-server.sock
FLUSHALL
quit
sudo -u www-data php occ files:scan --all -v
sudo -u www-data php occ files:scan-app-data -v
service nginx start

After Nextclouds files:scan all of your NAS data will appear in the Nextcloud file-app.
The permissions-script <permission.sh> should be enhanced to umount and mount the new mounted NAS share:

vi /root/permissions.sh

Add the red lines to the existing script:

#!/bin/bash
find /var/www/ -type f -print0 | xargs -0 chmod 0640
find /var/www/ -type d -print0 | xargs -0 chmod 0750
chown -R www-data:www-data /var/www/
chown -R www-data:www-data /upload_tmp/
umount //<NAS>/<share>
chown -R www-data:www-data /var/nc_data/
mount //<NAS>/<share>
chmod 0644 /var/www/nextcloud/.htaccess
chmod 0644 /var/www/nextcloud/.user.ini
chmod 600 /etc/letsencrypt/live/yourcloud.dedyn.io/fullchain.pem
chmod 600 /etc/letsencrypt/live/yourcloud.dedyn.io/privkey.pem
chmod 600 /etc/letsencrypt/live/yourcloud.dedyn.io/chain.pem
chmod 600 /etc/letsencrypt/live/yourcloud.dedyn.io/cert.pem
chmod 600 /etc/ssl/certs/dhparam.pem

Please substitute the red ones accordingly to your environment, then save and quit (:wq!) the file. From now, your NAS will always be available in Nextcloud for the specific user.


(b) mount an external hdd to your Nextcloud

We prepare the new drive ‘/dev/sda‘ for the use in Nextcloud. Please format it with an ‘ext4’ file system and mount it permanently with an entry in /etc/fstab.

Stop your server (NGINX, PHP, MariaDB, Redis) services and check the availability of the new drive:

sudo -s
service nginx stop && service php7.3-fpm stop && service redis-server stop && service mysql stop
fdisk -l /dev/sda

If available, make a new partition with the fdisk command.

fdisk /dev/sda
  1. Type ‘o’ to create a new partition table.
  2. Type ‘n’ to create a new partition.
  3. Choose the primary partition type, input ‘p’.
  4. Partition Number – we just need 1.
  5. Leave all default on the First sector and Last sector – Press Enter.
  6. Type ‘w’ and press enter to write the partition.

The ‘/dev/sda1’ partition has been created, now we have to format it to ‘ext4’ with the mkfs tool. Then check the volume size.

mkfs.ext4 /dev/sda1
fdisk -s /dev/sda1

Next, create a new local ‘nc_data’ directory and mount ‘/dev/sda1’ to that directory.

sudo mkdir -p /nc_data

To mount new disk permanently, we add the new mount configuration to the fstab file. Open fstab with vom:

vi /etc/fstab

Paste the configuration below at the end of the file.

/dev/sda1     /nc_data     ext4     defaults     0     1

Save fstab and exit:

Now mount the disk and make sure that there is no error.

mount -a
df -h

At least you have to move your current Nextcloud data direcory to the new mounted directory

chown -R www-data:www-data /nc_data
rsync -av /var/nc_data/ /nc_data

and point to it in Nextcloud’s config.php.

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

Change the data-directory

...
'datadirectory' => '/nc_data',
...

Finally restart your server services and perform a new filescan:

service nginx stop && service php7.3-fpm restart && service redis-server restart && service mysql restart
cd /var/www/nextcloud
redis-cli -s /var/run/redis/redis-server.sock 
quit
sudo -u www-data php occ files:scan --all -v
sudo -u www-data php occ files:scan-app-data -v
service nginx restart

From now, your Nextcloud data will be stored on your external HDD.


Install POSTFIX to send server mails

(a) configure fail2ban system-notification mails

(b) install apticron and configure system update-notification mails


First install two packages: postfix and libsasl2-modules

apt install postfix libsasl2-modules mailutils -y

and start configuring 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

cp /etc/postfix/main.cf /etc/postfix/main.cf.bak
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 complete but 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 = your.dedyn.io
mydomain = your.dedyn.io
myorigin = $mydomain
smtp_tls_CApath = /etc/ssl/certs
smtpd_tls_CApath = /etc/ssl/certs
smtpd_tls_received_header = yes
smtp_tls_loglevel = 1
smtpd_tls_loglevel = 1
smtpd_use_tls=yes
smtp_use_tls=yes
smtpd_tls_protocols = TLSv1.2, !TLSv1.1, !SSLv2, !SSLv3
smtp_tls_protocols = TLSv1.2, !TLSv1.1, !SSLv2, !SSLv3
smtpd_tls_ciphers = high
smtp_tls_ciphers = high
smtpd_tls_cert_file = /etc/letsencrypt/live/your.dedyn.io/fullchain.pem
smtpd_tls_key_file = /etc/letsencrypt/live/your.dedyn.io/privkey.pem
smtp_tls_cert_file = /etc/letsencrypt/live/your.dedyn.io/fullchain.pem
smtp_tls_key_file = /etc/letsencrypt/live/your.dedyn.io/privkey.pem
alias_maps = hash:/etc/aliases
alias_database = hash:/etc/aliases
mydestination = $myhostname, your.dedyn.io, localhost.localdomain, localhost
relayhost = your.mail-smtpserver.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
compatibility_level=2

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

vi /etc/postfix/sasl_password

Enter your credentials like exemplarily shown

your.mail-smtpserver.com a987654:PassWorD

and change the access level of this file to 600.

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:

vi /etc/postfix/main.cf

If not exists 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 youremail@domain.com
www-data youremail@domain.com
<your-ubuntuuser-name> youremail@domain.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 "Postfix-Testmail" yourmail@domain.com < testmail.txt

Check the logfile

cat /var/log/mail.log

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

Postfix administration tasks:

[a] have a look in your actual mailqueue: mailq

[b] flush / re-send your mail(s)-queue: postfix flush

[c] delete all mails in your mailqueue: postsuper -d ALL


(a) configure fail2ban system-notification 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

cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.conf.bak
vi /etc/fail2ban/jail.conf

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

...
destemail = yourmail@domain.com
...
sender = yourmail@domain.com
...
mta = mail
...
# action = %(action_)s
action = %(action_mwl)s
...

Save and quit (:wq!) the fail2ban configuration. To avoid (many) mails on every fail2ban-restart just create a new file and copy it as shown below:

vi /etc/fail2ban/action.d/mail-buffered.local

Paste the following rows

[Definition]
actionstart =
actionstop =

Copy the file

cp /etc/fail2ban/action.d/mail-buffered.local /etc/fail2ban/action.d/mail.local
cp /etc/fail2ban/action.d/mail-buffered.local /etc/fail2ban/action.d/mail-whois-lines.local
cp /etc/fail2ban/action.d/mail-buffered.local /etc/fail2ban/action.d/mail-whois.local
cp /etc/fail2ban/action.d/mail-buffered.local /etc/fail2ban/action.d/sendmail-buffered.local
cp /etc/fail2ban/action.d/mail-buffered.local /etc/fail2ban/action.d/sendmail-common.local

Re-start the fail2ban-service an you will (only) be informed if fail2ban blocked new IPs

service fail2ban restart

automatically.


(b) install apticron and configure system update-notification mails

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

apt install apticron -y

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

cp /etc/apticron/apticron.conf /etc/apticron/apticron.conf.bak
vi /etc/apticron/apticron.conf
...
EMAIL="yourmail@domain.com"
...
SYSTEM="yourmail@domain.com"
...
NOTIFY_HOLDS="1"
...
NOTIFY_NO_UPDATES="1"
...
CUSTOM_SUBJECT='$SYSTEM: $NUM_PACKAGES package update(s)'
...
CUSTOM_NO_UPDATES_SUBJECT='$SYSTEM: no updates available'
...
CUSTOM_FROM="yourmail@domain.com"
...

To run and check APTICRON just call

apticron

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

cp /etc/cron.d/apticron /etc/cron.d/apticron.bak
vi /etc/cron.d/apticron
30 7 * * * root if test -x /usr/sbin/apticron; then /usr/sbin/apticron --cron; else true; fi

Apticron will now be executed by cron.d. You can change the starttime e.g. to daily 7.30 AM.


A second factor for ssh (2FA – two factor authentication)

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 your preferred OTP AUTH app

apt install libpam-google-authenticator -y

Leave the root-Shell and run the following command as your <your-ubuntu-user-name> and NOT as root:

exit
google-authenticator

You will be asked for:

Do you want authentication tokens to be time-based (y/n) y
&copy; 2016, c-rieger.de
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 back to the root-Shell

sudo -s

Backup the current configuration and configure your ssh server

cp /etc/pam.d/sshd /etc/pam.d/sshd.bak
vi /etc/pam.d/sshd

Change the file to mine:

@include common-auth
@include common-password
auth required pam_google_authenticator.so
account required pam_nologin.so
@include common-account
session [success=ok ignore=ignore module_unknown=ignore default=bad] pam_selinux.so close
session required pam_loginuid.so
session optional pam_keyinit.so force revoke
@include common-session
session optional pam_motd.so motd=/run/motd.dynamic
session optional pam_motd.so noupdate
session optional pam_mail.so standard noenv # [1]
session required pam_limits.so
session required pam_env.so # [1]
session required pam_env.so user_readenv=1 envfile=/etc/default/locale
session [success=ok ignore=ignore module_unknown=ignore default=bad] pam_selinux.so open

Save and quit (:wq!) the file.

If not already created please create your 4096 bit RSA Key (SSH) first:

cd ~
ssh-keygen -q -f /etc/ssh/ssh_host_rsa_key -N '' -b 4096 -t rsa

If you will be asked to overwrite the existing key, confirm with ‘Y’. Then backup, edit and change your SSH-config to examplarily mine

mv /etc/ssh/sshd_config /etc/ssh/sshd_config.bak
vi /etc/ssh/sshd_config
# Port 22
Port 1234 #your decision, but keep UFW in mind!
Protocol 2
HostKey /etc/ssh/ssh_host_rsa_key
HostKey /etc/ssh/ssh_host_ecdsa_key
HostKey /etc/ssh/ssh_host_ed25519_key
UsePrivilegeSeparation yes
KeyRegenerationInterval 3600
ServerKeyBits 4096
SyslogFacility AUTH
LogLevel INFO
LoginGraceTime 30s
PermitRootLogin no
StrictModes yes
RSAAuthentication yes
PubkeyAuthentication yes
IgnoreRhosts yes
UseDNS yes
RhostsRSAAuthentication no
HostbasedAuthentication no
IgnoreUserKnownHosts yes
PermitEmptyPasswords no
MaxAuthTries 3
MaxSessions 3
ChallengeResponseAuthentication yes
X11Forwarding yes
X11DisplayOffset 10
X11UseLocalhost no
PrintMotd no
PrintLastLog yes
TCPKeepAlive yes
Banner /etc/issue
AcceptEnv LANG LC_*
Subsystem sftp /usr/lib/openssh/sftp-server
UsePAM yes
AllowTcpForwarding no
AllowUsers ubuntuuser #<your-ubuntu-user-name> for e.g. putty or ssh native
AuthenticationMethods publickey,password publickey,keyboard-interactive

If you changed the ssh-Port to e.g. 1234, please ensure having changed your ufw-configuration either and adjust the username in ‘AllowUsers ubuntuuser.

Paste your public key to the <ubuntuuser>’s keystore (ubuntu’s how-to):

vi ~/.ssh/authorized_keys

and set proper permissions:

sudo chown -R ubuntuuser:ubuntuuser ~/.ssh
sudo chmod 700 ~/.ssh
sudo chmod 600 ~/.ssh/authorized_keys

Then restart your ssh server

service ssh restart

and re-logon to your server using a new session-window. This is your final fallback, if you misconfigured your ssh server ;-). From now your privat key is needed, you will be prompted for your password and finally for your new second factor.

Public Key authentication and ssh-user password

Verification code (OTP 2FA)

Start your e.g. OTP AUTH or Google Authenticator app and read your second factor to gain access to your server.

Logged on

You will be logged on using your second factor.


Enjoy your personal data in your secured and hardened Nextcloud-Server!

Don’t forget to backup your Nextcloud

Find more instructions here: Nextcloud Backup and Restore



Carsten Rieger

Carsten Rieger

Carsten Rieger is a senior system engineer in full-time and also working as an IT freelancer. He is working with linux environments for more than 13 years, an Open Source enthusiast and highly motivated on linux installation and troubleshooting. Mostly working with Debian/Ubuntu Linux, Nginx and Apache web server, MariaDB/MySQL/PostgreSQL, PHP, Cloud infrastructure (e.g. Nextcloud) and other open source projects (e.g. Roundcube) and in voluntary work for the Dr. Michael & Angela Jacobi Stiftung for more than 7 years.

260 Responses

  1. Marcelo Oliveira says:

    Just getting started with this guide and I’m receiving this in error log upon trying to start nginx service:

    — Unit nginx.service has begun starting up.
    Aug 15 05:28:33 cloud nginx[12719]: nginx: [emerg] “user” directive is duplicate in /etc/nginx/nginx.conf:5
    Aug 15 05:28:33 cloud systemd[1]: nginx.service: Control process exited, code=exited status=1
    Aug 15 05:28:33 cloud systemd[1]: nginx.service: Failed with result ‘exit-code’.
    Aug 15 05:28:33 cloud systemd[1]: Failed to start nginx – high performance web server.
    — Subject: Unit nginx.service has failed
    — Defined-By: systemd
    — Support: http://www.ubuntu.com/support

    — Unit nginx.service has failed.

    Something I’m missing? I tried to Google, but no one with exact issue. I hope you can help.

  2. Falk says:

    Hi Carsten,

    I tried multiple installations of a nextcloud on my xu4 with a cloudshell 2 case and so far none worked and all failed at the same step.

    By following this guide only or trying the shell script to automate the installation the error that appears is always related to missing repositories of either mp4 or a (nextcloud nginx[4230]: nginx: [emerg] unknown directive “mp4” in /etc/nginx/conf.d/nextcloud.conf:41).
    A similar problem was already mentioned by Robin in April in this comment section and I followed your advice to him to follow the guide but it didn’t solve the problem for me. Later I found the comment of Karsten(3rd of Aug) that the mp4 directive could only be included if nginx would be compiled “by hand” which you described in an earlier guide(https://www.c-rieger.de/nextcloud-installation-guide-advanced/#c01) as you replied. So I followed that earlier guide for installing nginx and switched back to this one for the rest of the installation but I still get an error message at the same step, that is when restarting nginx after the dhparam creation (sed -i s/#include/include/g /etc/nginx/nginx.conf && service nginx restart). Only this time the error message is not related to a missing directive anymore but to ssl_certification. I checked if the dhparam.pem was created successfully and it was.

    The specific error that I get is:
    ● nginx.service – nginx – high performance web server
    Loaded: loaded (/lib/systemd/system/nginx.service; enabled; vendor preset: enabled)
    Active: failed (Result: exit-code) since Sat 2018-08-11 20:01:10 UTC; 16s ago
    Docs: http://nginx.org/en/docs/
    Process: 19874 ExecStop=/bin/kill -s TERM $MAINPID (code=exited, status=0/SUCCESS)
    Process: 19876 ExecStart=/usr/sbin/nginx -c /etc/nginx/nginx.conf (code=exited, status=1/FAILURE)
    Main PID: 503 (code=exited, status=0/SUCCESS)

    Aug 11 20:01:10 odroid systemd[1]: Starting nginx – high performance web server…
    Aug 11 20:01:10 odroid nginx[19876]: nginx: [emerg] no “ssl_certificate” is defined for the “listen … ssl” directive in /e
    Aug 11 20:01:10 odroid systemd[1]: nginx.service: Control process exited, code=exited status=1
    Aug 11 20:01:10 odroid systemd[1]: nginx.service: Failed with result ‘exit-code’.
    Aug 11 20:01:10 odroid systemd[1]: Failed to start nginx – high performance web server.

    At this point I am out of ideas for where I could make changes or which other combination of guides I could follow.
    If you could point me a direction for where to look I would gladly appreciate it.

    Greetings,

    Falk

  3. Karsten says:

    Hello Carsten,
    it seems as per http://nginx.org/en/linux_packages.html#mainline only x86_64 is available.
    So for example to use an ODROID-C2 I would have to compile it myself to get an actual 1.15.2 with mp4 support?

    Greetings

  4. Robin says:

    The new update in the guide works for already installed Nextcloud’s also.
    The first line update everything OK.

    The second line gives the following:
    root@nextcloud:~# sudo -u www-data php /var/www/nextcloud/occ db:convert-filecache-bigint
    All tables already up to date!

    But I guess that’s OK.

  5. giulio says:

    Hi, great job!
    How can I make use of this letsencrypt obtained with webmin? When I log in to mydomine: 10000 chrome tells me that I have problems because it uses HSTS

  6. Robin says:

    Hi,
    After updating mariadb I get this email from “root” every night:

    /etc/cron.daily/logrotate:
    logrotate_script: 3: [: /var/run/mysqld/mysqld.pid: unexpected operator

    how can I fix this? 🙂

  7. Cardano says:

    Hey, first of all, Thank you so much for this tutorial !
    After motnhs running stable my cronjob aren’t working ;anymore while everything looks normal .
    And when i run optimize.sh(the 2 last command in that file) i got this error : Allowed memory size of 2097152 bytes exhausted (tried to allocate 36864 bytes) in /var/www/nextcloud/3rdparty/composer/autoload_static.php on line 2432

    • Cardano says:

      Never mind , i just fixed it by increasing memory limit in the different php.ini files . I don’t know what happend tho

  8. Rainer says:

    Hi Carsten,

    Du hast ja geschrieben, dass Du derzeit sehr ausgelastet bist, ich bekomme nach diesem Befehl:

    add-apt-repository ppa:certbot/certbot -y && apt update && apt upgrade -y && apt install letsencrypt -y

    diesen Fehler angezeigt:

    UnicodeDecodeError: ‘utf-8’ codec can’t decode byte 0xfc in position 17: invalid start byte

    Kannst Du mir hier kurz weiterhelfen?

    Grüße
    Rainer

  9. johnz says:

    and from the error log i have this error
    2018/07/13 01:24:57 [error] 1724#1724: *185 recv() failed (104: Connection reset by peer) while reading response header from upstream, client: 192.168.113.2, server: cloud.mifo.gr, request: “GET /apps/w2g2/lock?files=[[“9″,”Documents”,null,””,null,”dir”],[“3″,”Photos”,null,””,null,”dir”],[“530″,”SMB”,null,””,null,”dir”],[“8″,”Nextcloud.mp4″,null,””,null,”file”],[“7″,”Nextcloud+Manual.pdf”,null,””,null,”file”],[“157897″,”test.odt”,null,””,null,”file”],[“156528″,”testdoc”,null,””,null,”file”]]&folder=/ HTTP/1.1″, upstream: “fastcgi://unix:/run/php/php7.2-fpm.sock:”, host: “cloud.mifo.gr”
    2018/07/13 04:59:05 [error] 1724#1724: *849 recv() failed (104: Connection reset by peer) while reading response header from upstream, client: 192.168.113.2, server: cloud.mifo.gr, request: “GET /apps/w2g2/lock?files=[[“9″,”Documents”,null,””,null,”dir”],[“3″,”Photos”,null,””,null,”dir”],[“530″,”SMB”,null,””,null,”dir”],[“8″,”Nextcloud.mp4″,null,””,null,”file”],[“7″,”Nextcloud+Manual.pdf”,null,””,null,”file”],[“157897″,”test.odt”,null,””,null,”file”],[“156528″,”testdoc”,null,””,null,”file”]]&folder=/ HTTP/1.1″, upstream: “fastcgi://unix:/run/php/php7.2-fpm.sock:”, host: “cloud.mifo.gr”
    2018/07/13 05:01:49 [error] 1724#1724: *981 FastCGI sent in stderr: “Primary script unknown” while reading response header from upstream, client: 94.66.222.74, server: cloud.mifo.gr, request: “GET /nextcloud/index.php/apps/files/api/v1/thumbnail/256/256/Nextcloud.mp4 HTTP/1.1”, upstream: “fastcgi://unix:/run/php/php7.2-fpm.sock:”, host: “cloud.mifo.gr”
    2018/07/13 05:02:19 [error] 1724#1724: *1007 FastCGI sent in stderr: “Primary script unknown” while reading response header from upstream, client: 94.66.222.74, server: cloud.mifo.gr, request: “GET /nextcloud/index.php/apps/files/api/v1/thumbnail/256/256/Nextcloud.mp4 HTTP/1.1”, upstream: “fastcgi://unix:/run/php/php7.2-fpm.sock:”, host: “cloud.mifo.gr”
    2018/07/13 05:03:23 [error] 1724#1724: *1007 FastCGI sent in stderr: “Primary script unknown” while reading response header from upstream, client: 94.66.222.74, server: cloud.mifo.gr, request: “GET /nextcloud/index.php/apps/files/api/v1/thumbnail/256/256/Nextcloud.mp4 HTTP/1.1”, upstream: “fastcgi://unix:/run/php/php7.2-fpm.sock:”, host: “cloud.mifo.gr”
    2018/07/13 05:04:09 [error] 1724#1724: *1006 FastCGI sent in stderr: “Primary script unknown” while reading response header from upstream, client: 94.66.222.74, server: cloud.mifo.gr, request: “GET /nextcloud/index.php/apps/files/api/v1/thumbnail/256/256/Nextcloud.mp4 HTTP/1.1”, upstream: “fastcgi://unix:/run/php/php7.2-fpm.sock:”, host: “cloud.mifo.gr”

    do you have any idea for that ?
    i think the problem is with web server confing

  10. johnz says:

    hello
    thanks for your script , untill now i use only apache ,but with your script i try the nginx ,but
    i have a serius problem with smbclient , Module ‘smbclient’ already loaded at Unknown#0
    And with androip mobile app i cann’t explore my smb share (smb share is windows 2012R2)
    nextcloud 13.04 ,with ubundu 18.04 ,full update, intrgration with AD
    have you any suggestion for that issue ?

  11. Patrick Chou says:

    Hi! Do you know why fail2ban is always blocking my WAN IP when someone is trying to bruteforce the Nextcloud site? Already tried to bruteforce it by myself when I was connected via 4G with IP address that I know but the blocked ip was not the 4G, but the ip that is provided from the ISP – where is connected the router and the Odroid C2 server. After the jail is activated nobody can connect to the cloud, no mather what is their ip address.
    Thanks!

    • Strange behaviour! Were your IPs forwared properly (xff) or were the local IPs written to the logs? How did you configure fail2ban and what was written to your nextcloud.log?

  12. Marcus says:

    Hallo,

    ist es möglich es so einzurichten, dass dies ohne direkte Weiterleitung zur DynDNS geh? Sprich wenn ich meine IP 192.168.178.X des Server lokal eingebe?

    • Guten Morgen Marcus, wenn ich Dich richtig verstehe lautet die Antwort ja. Die NGINX Konfiguration (nextcloud.conf) sollte zusätzlich zu der Domain auch die IP enthalten (server_name YOUR.DEDYN.IO 192.168.178.X;) und in der /var/www/nextcloud/config/config.php die IP-Adresse als trusted-domain ergänzt (sudo -u www-data php /var/www/nextcloud/occ config:system:set trusted_domains 1 –value=192.168.178.X) und der overwrite.cli.url Eintrag entfernt werden. Meintest Du das?

  13. Robin says:

    Hi,
    Regarding this update:
    July, 8th 2018:
    – MariaDB changes: transaction_isolation = READ-COMMITTED, binlog_format = ROW

    Can I that already have a Nextcloud server running change this?
    Or do I break something then?

    • Hi Robin, yes you can! Please follow these steps:
      sudo -s
      sudo -u www-data /var/www/nextcloud/occ maintenance:mode --on
      service nginx stop && service mysql stop
      cp /etc/mysql.my.cnf /etc/mysql.my.cnf.bak
      vi /etc/mysql.my.cnf

      Make your changes
      transaction_isolation = READ-COMMITTED
      binlog_format = ROW

      Restart your services
      service mysql restart && service nginx restart

      Disable Nextclouds maintenance mode:
      sudo -u www-data /var/www/nextcloud/occ maintenance:mode --off

      • Karsten says:

        wouldn’t it be
        “sudo -u www-data php /var/www/nextcloud/occ maintenance:mode –on”
        and
        “sudo -u www-data php /var/www/nextcloud/occ maintenance:mode –off” ?

  14. Love your walk-through! I got it working a month or so back but ran into a functional snag at the end. I decided to start a small blog to document these experiences to serve as my own documentation and to help others (hopefully). I linked this guide at my site as I hope you don’t mind.

    My question being a little new to wordpress, what syntax plugin do you use for your code-blocks?

  15. Rainer says:

    Hallo Carsten,

    ich hatte Nextcloud im Mai installiert. Läuft soweit auch alles. Aber jetzt erst habe ich den Client getestet und erhalte die folgende Fehlermeldung, wenn ich eine Datei/Ordner über den Client an eine externe E-Mail Adresse verschicken möchte:

    “Sharing test.jpg failed, could not find meine@emailadresse.de, maybe the server is currently unreachable or uses a self-signed certificate.”

    Wenn ich das über die die Weboberfläche mache, klappts. Hier es allerdings so, dass mir die externe Mailadresse zweimal angezeigt wird, einmal in Klammern mit “entfernt”, wenn ich das anklicke, erscheint die gleiche Fehlermeldung,
    und einmal in Klammern mit “E-Mail”, wenn ich das nehme, klappts. Scheint also so zu sein, dass der Client mir nur die erste Option anbietet u. deshalb die gleiche Fehlermeldung erscheint. Hast Du eine Idee, woran das liegen könnte?

    VG
    Rainer

  16. Francis says:

    Hi Carsten,

    thanks for your tutorial!

    Since changes from latest updates in the guide, I cannot start the nginx service anymore. Getting this error :

    nginx.service – nginx – high performance web server
    Loaded: loaded (/lib/systemd/system/nginx.service; enabled; vendor preset: enabled)
    Active: failed (Result: exit-code) since lun 2018-07-02 17:57:28 EDT; 3s ago
    Docs: http://nginx.org/en/docs/
    Process: 25555 ExecStart=/usr/sbin/nginx -c /etc/nginx/nginx.conf (code=exited, status=1/FAILURE)

    jui 02 17:57:28 server systemd[1]: Starting nginx – high performance web server…
    jui 02 17:57:28 server nginx[25555]: nginx: [emerg] no “ssl_certificate” is defined for the “listen … ssl” directive in /etc/nginx/conf.d/nextcloud.conf:13
    jui 02 17:57:28 server systemd[1]: nginx.service: Control process exited, code=exited status=1
    jui 02 17:57:28 server systemd[1]: Failed to start nginx – high performance web server.
    jui 02 17:57:28 server systemd[1]: nginx.service: Unit entered failed state.
    jui 02 17:57:28 server systemd[1]: nginx.service: Failed with result ‘exit-code’.

    I tried to check against your version and all my files where OK. I tried to generate new certificates too and the error persists.

    Could you help me please?

    • Please verify your path to your certificates in your ssl.conf.
      A suffix (_1) might have been added while you did a new request. Ensure your ssl.conf is not commented in your nginx.conf as well. If you will still run in trouble please zip your conf files and drop them here.

      • Francis says:

        Hi,

        I just upload the config files but just after, I realized that ssl.conf, proxy.conf, header.conf and optimization.conf were commented in nginx.conf. I uncommented them and the service started fine.

        However, when I’m trying to access nextcloud now, I get an “DNS_PROBE_FINISHED_NXDOMAIN” error. What could it be?

        Regards

        • Francis says:

          I get this error “DNS_PROBE_FINISHED_NXDOMAIN” only inside my network. Via external network I can access it.

          Thank you.

          Francis

  17. Daniel says:

    Hi Carsten, vielen Dank für das mega Tutorial, es funktioniert auch alles wie gewünscht. Ich habe nur ein etwas seltsames verhalten. Beim Upload von Dateien (>100MB) fällt mir auf, dass ich je Browser-Session einen max. Upload von 7-8Mbit erhalte (auch bei 2, oder 3 gleichzeitigen Uploads, über mehrere Browser-Fenster verteilt). Der Server ist mit 100Mbit (Up/Down) am Netz. Über die Nextcloud-App “Flowupload” oder Webdav bekomme ich deutlich höhere Raten. Hast du eine Idee dazu, wo hier das Bottle-Neck sein könnte? Vielen Dank im Voraus…

    • Ich sehe keinen Zusammenhang mit der Nextcloud. Hier spielt eher Netzwerktechnik eine Rolle. Ist der Server im LAN o. im WAN mit 100/100 erreichbar? Ich denke, Dir steht zwar diese Bandbreite technisch zur Verfügung, diese wird aber bei der Kommunikation aufgeteilt und wieder zusammengesetzt. Bitte wende Dich an Deinen Provider o. an die Community.

  18. Marco says:

    Hey, i was wondering if it’s possible to use multiple hdd for data storage, does it require some extra config?
    Also is it a good idea / makes it faster to install ubuntu on an SD drive but the cloud data on the hdd/s ?

    • This can be done by RAID, by Nextclouds External Storage App, by mount NAS, etc…from my perspective no generic solution exists.
      Yes, it would make sense to operate on a SSD and e.g. on “normal” HDD or NAS devices for your cloud data. Cheers, Carsten

      • Marco says:

        I was able to put online a test version (with a test hdd) of my server with your guide, thank you for that!
        Another question i have now, for what is the backup needed? Does it saves the files or only the configs? And if so, do you have to put it on a safe drive in case your hdd dies?
        I plan to do a RAID 1 configuraton (so a full copy of files) do i still need to do a backup?

        Really much appreciate your work, thank you for everything!

  19. Robin says:

    I’m wondering what changes you did with the nginx.conf file during this update:
    June, 13th 2018:
    – updated the nginx.conf and added a “server security verification”

  20. Bruno says:

    Hello Carsten,

    Thanks a lot for the tutorial!
    Can you help me understand why you’re using snakeoil certificates instead of the letsencrypt ones in ssl.conf nginx file?
    ssl_certificate /etc/ssl/certs/ssl-cert-snakeoil.pem;
    ssl_certificate_key /etc/ssl/private/ssl-cert-snakeoil.key;
    ssl_trusted_certificate /etc/ssl/certs/ssl-cert-snakeoil.pem;
    #ssl_certificate /etc/letsencrypt/live/YOUR.DEDYN.IO/fullchain.pem;
    #ssl_certificate_key /etc/letsencrypt/live/YOUR.DEDYN.IO/privkey.pem;
    #ssl_trusted_certificate /etc/letsencrypt/live/YOUR.DEDYN.IO/chain.pem;

    Thanks and cheers,
    Bruno

    • these scripts were used temporarily until you request your certificates. In a following step the rows will be deleted and the others uncommented by issuing
      sed -i '/ssl-cert-snakeoil/d' /etc/nginx/ssl.conf
      sed -i s/#ssl/ssl/g /etc/nginx/ssl.conf

  21. Nick says:

    Carsten, thanks for this EXCELLENT article. I’ve managed to create another NC instance by following your instruction.

    However, when I attempted to add on this new instance with another EXCELLENT article of yours (adding clamav, found here: https://www.c-rieger.de/nextcloud-more-secure-using-clamav/). I get all the way down to “Change to the admin panel and select Additional Settings”, I don’t see “Antivirus Configuration” section.

    Any thoughts/suggestions is greatly appreciated!

  22. Bart says:

    Thank you very much for this tutorial!!

    I am a bit of a noob but trying to understand instead of just copy pasting 🙂 I have a question about “Harden your System using fail2ban….” I suppose it doesn’t matter whether you use Nginx or apache for these settings. Could you maybe shine some light on the rules? What do they actually mean. Seem quite complicated to me 🙂

    Kind regards

    Bart

    • Hi Bart,

      ^{"reqId":".*","remoteAddr":".*","app":"core","message":"Login failed: '.*' (Remote IP: 'HOST')","level":2,"time":".*"}$
      ^{"reqId":".*","level":2,"time":".*","remoteAddr":".*","app":"core".*","message":"Login failed: '.*' (Remote IP: 'HOST')".*}$

      The Nextcloud logfile will be parsed using this regular expressions concerning “LOGIN FAILED”
      ^.*"remoteAddr":"HOST".*Trusted domain error.*$
      The Nextcloud logfile will be parsed using this regular expressions concerning “TRUSTED DOMAIN ERRORS”

      HOST is the placeholder for the remote-IP – this IP would be blocked if fail2ban rules grab.
      Regards, Carsten

  23. Sven says:

    Hi, first of all: Thank you!!! 🙂
    Now to my question: i followed your guide step by step but now im at the step where i want to request my ssl certificates from letsencrypt.
    i tried but i got the following error: The server could not connect to the client to verify the domain :: Fetching http:///.well-known/acme-challenge/
    First i thought i forgot to adjust my firewall settings, but they are fine. Then i checked if nginx was running and i found out that nginx couldn’t be started.
    I tried “service nginx restart” but i get the following error:

    root@nextcloud:/etc/nginx/conf.d# service nginx restart
    Job for nginx.service failed because the control process exited with error code.
    See “systemctl status nginx.service” and “journalctl -xe” for details.

    When i use “systemctl status nginx.service” i get:
    ● nginx.service – nginx – high performance web server
    Loaded: loaded (/lib/systemd/system/nginx.service; enabled; vendor preset: enabled)
    Active: failed (Result: exit-code) since Sat 2018-06-16 08:39:30 UTC; 54s ago
    Docs: http://nginx.org/en/docs/
    Process: 2342 ExecStart=/usr/sbin/nginx -c /etc/nginx/nginx.conf (code=exited, status=1/FAILURE)

    Jun 16 08:39:30 nextcloud systemd[1]: Starting nginx – high performance web server…
    Jun 16 08:39:30 nextcloud nginx[2342]: nginx: [emerg] no “ssl_certificate” is defined for the “listen … ssl” directive in /etc/nginx/conf.d/nextcloud.conf:15
    Jun 16 08:39:30 nextcloud systemd[1]: nginx.service: Control process exited, code=exited status=1
    Jun 16 08:39:30 nextcloud systemd[1]: nginx.service: Failed with result ‘exit-code’.
    Jun 16 08:39:30 nextcloud systemd[1]: Failed to start nginx – high performance web server.

    In /etc/nginx/conf.d/nextcloud.conf:15 the server block for the ssl vhost starts.
    I copied yours but it seems nginx is missing the listen … ssl directories.

    Can you please help me out here?

  24. OverMark says:

    Hi!
    Amazing article! Congratulations! By far the most detailed help that I’ve found.

    I’ve followed it step by step but I’ve changed:
    – Letsecrypt cert with one of mine.
    – Data is in a secondary disk.

    After installing NextCloud, I’m facing a login infinite loop: https://mydomain.com/login –> https://mydomain.com/login?redirect_url=/apps/files/

    But it’s the same login page and it stays here forever. No matter how many times I tried to login.

    Can you help me please?

    Thanks!

  25. Edgard says:

    Hi,

    I have Deluge without SSL and using port 8112 running on the same server. But when I try to connect to the address using the DNS name http://web.server.com:8112, I’m automatically forwarded to http insteads. However, I don’t have that problem if I use the IP addres instead so http://192.168.1.10:8112 is working.

    So my question is, is it possible to disable the http to https auto forwarding for other ports than port 80?

  26. Robin says:

    When I changing to:
    deb http://nginx.org/packages/mainline/ubuntu/ bionic nginx
    deb-src http://nginx.org/packages/mainline/ubuntu/ bionic nginx

    from:
    deb http://nginx.org/packages/mainline/ubuntu/ xenial nginx
    deb-src http://nginx.org/packages/mainline/ubuntu/ xenial nginx

    I get this error:
    N: Skipping acquire of configured file ‘nginx/binary-i386/Packages’ as repository ‘http://nginx.org/packages/mainline/ubuntu bionic InRelease’ doesn’t support architecture ‘i386’

    How can I fix it?

    Thanks.

  27. Bartos says:

    Hallo Carsten,

    zu erst vielen Dank! Ich habe selten solch eine professionelle Anleitung gesehen. Ich habe nur noch ein frage zu fail2ban. Ich betreibe die Cloud hinter einer Sophos Firewall und setze die Web Application Firewall der Sophos ein(Reverse Proxy). Diese unterstützt das weitergeben der realen IP der Clients über den X-Forwarded-For-Header. Was muss ich machen damit der fail2ban Jail diese IP für seine Auswertung nutzt? Muss ich überhaupt was umstellen?

    Mit freundlichen Grüßen

    Bartos

  28. Viktorio says:

    Hi Carsten!

    Thanks for this wonderful step by step tutorial. It just works flawless although I am not a Linux guru . Some day if you have the time of course, can you show us how to setup “Nextcloud Talk”? I’ve already tried https://help.nextcloud.com/t/howto-setup-nextcloud-talk-with-turn-server/30794 but unfortunately with no result.

    Thanks again!

  29. Larry says:

    This is by far the most excellent article on how to install NextCloud on Ubuntu. I used your article for 16.04, and just used it for 18.04. I have never seen anything that is not only so complete, but actually works very well. Thank you again. By the way, I was able to install using this guide on an ARM server with no issues. Thank you!

  30. Edgard says:

    Well, it’s working now 🙂

    The certificate was OK, but I still remade my config.php file and now everything work. I probably made a mistake in my copy/paste somewhere at that step… :-/

    Really sorry for disturbing you for nothing and thanks a lot for your help!!! (And for your article :-)))))))

  31. Edgard says:

    Thanks a lot for your article, but I do have a problem when at the “Logon to your brandly new Nextcloud in your browser” step. I did everything exactly like in the article on a newly installed Ubuntu 18.04 and didn’t received any error during the process until there.

    Firefox is giving me the error : Secure Connection Failed. The connection was interrupted while the page was loading. The page you are trying to view cannot be shown because the authenticity of the received data could not be verified.
    And IE is giving this one : Can’t connect securely to this page. This might be because the site uses outdated or unsafe TLS security settings. If this keeps happening, try contacting the website’s owner.

    A CURL is giivng me the following result : curl: (35) OpenSSL SSL_connect: SSL_ERROR_SYSCALL

    Would you have an idea at what I did wrong?

  32. Semko says:

    Hello Mr. Rieger.

    Because I’m planing to build my own energy efficient server, I have already read a few tutorials on the Internet, and I can say – This website is completely different beer! On this pages I found almost everything that I need. You seem very familiar with this matter. That’s why I’d like to ask You a few question.

    Can You please suggest me what kind of hardware is good choice for a project including:
    – OS – Ubuntu – 18.04;
    – Web Server – Nginx/Php/MariaDB/Wordpress;
    – Cloud server – Nextcloud;
    – Mail server – Postfix, Dovecot, SpamAssassin;
    – XMPP server – Prosody;

    The main goal is: Small, quiet, energy efficient system/board for 5 to max. 10 users.

    I know that ARM based SBC can work 24/7 for years with no problems at all , and most important for me – without active cooling. Just hate noisy things in my house. But I’m not sure if an ARM based SBC can handle all that.
    I’m more than sure that an Intel NUC with i5 processor is decades ahead, but I have no idea if it is OK with this 24/7 working cycle. And also not sure how noisy it is going to be.

    Every suggestion is highly appreciated.

    Thanks for Your time!

    • Dear Semko, thank you very much. It depends on the amount of data and where to store all your data. It would be absolutely sufficient to use an odroid c2 or rock64 (0/zero db) or an intel nuc as i do (NUC6CAYH, noisless if you reduce the rpm in bios / 24/7 since 1,5 years.) My data are stored on a Synology DS and are mounted to Nextcloud (/etc/fstab ~ 2TB). It is already discussed in the Nextcloud Forum / Best cheap hardware. But for sure: both, the odroid C2 as well the NUC would be sufficient regarding your described purposes. Cheers, Carsten

  33. Robin says:

    Hi,
    Sorry for all of my questions but in the nextcloud.conf file it’s a line proxy_pass http://127.0.0.1:81; and if I’m using the port 80 should I adjust that to 80 or should I still have it on 81?
    The port’s that are open @ my server is port 80 and 443

  34. Pisoko says:

    Hey Carsten, wie immer super HowTo!
    Mir ist bei meiner Installation (~200user) aufgefallen, dass das /usr/local/tmp/sessions sehr schnell voll läuft und die user sich anschließend nicht mehr anmelden können.
    Du solltest vielleicht ein cronjob schreiben, der diese tmp folders alle paar tage frei räumt.

    Viele Grüße

    • Vielen Dank! Es gibt ja einen cronjob, der das sogar stündlich zwei Mal tut. Dieser wird bei den PHP-Modifikationen mit angelegt (crontab -l ; echo "09,39 * * * * /usr/lib/php/sessionclean 2>&1") | crontab -u root -

  35. Bernd says:

    Nachdem ich Deine Anleitung durchgearbeitet habe kriege ich noch folgende Meldung in den Grundeinstellungen angezeigt:

    Dieser Server hat keine funktionierende Internetverbindung: Mehrere Ziele konnten nicht erreicht werden. Dies bedeutet, dass einige Funktionen, wie das Einhängen exernen Speichers, Benachrichtigungen über Updates oder die Installation von Drittanbieter-Apps nicht funktionieren. Der Zugriff auf entfernte Dateien und das Senden von E-Mail-Benachrichtigungen wird wahrscheinlich ebenfalls nicht funktionieren. Um alle Funktionen nutzen zu können, stelle eine Internet-Verbindung für diesen Server her.

    Google.de oder Nextcloud.com kann ich erfolgreich anpingen

    • Hast Du in der nginx.conf die Resolver-IP und in der nextcloud.conf den Servernamen angepasst? Was steht in den Logfiles?

      • Bernd says:

        Ich bin am Wochenende etwas weiter gekommen:
        Ich habe die Zeile “requirepass ” in der redis.conf (in Deinem Tutorial eh nur optional) mal auskommentiert und siehe da: nun kriege ich die Fehlermeldung nicht mehr und Nextcloud rennt, wie es sollt.
        Verstanden habe ich den redis-Teil nicht…kann im Moment auch gut damit leben; würde nur erstmal die Zusammenhänge verstehen wollen.

  36. @Carsten: Would it be interresting to include the GeoIP Module in the nginx, to be able to further block request by locations ?

  37. Is it possible to get an automatic mail, when updates appear to your very nice script?
    Thanks in advance

  38. Robin says:

    Hi,
    I can see that you have updated some things in the guide, and I’m wondering if we that did install it before your updates should also change it?

    Create and add optimize.sh to root crontab

    And also do the changes to the config.php

    • Robin says:

      I can’t edit the post above but I was wondering what you have changed in the config.php file?

      • I just updated the process of making ammendments to the config.php not the content itself.

        • Robin says:

          OK I see,
          When I’m trying to run the optimize.sh script I get this:
          root@nextcloud:~# /root/optimize.sh
          (error) NOAUTH Authentication required.

          Scanning AppData for files

          +———+——-+————–+
          | Folders | Files | Elapsed time |
          +———+——-+————–+
          | 1506 | 3066 | 00:00:03 |
          +———+——-+————–+

          I’m wondering over (error) NOAUTH Authentication required. whats that?

          I have change the script a little because all of my shares is trough SMB but I only deleted this line from the script:
          sudo -u www-data php /var/www/nextcloud/occ files:scan –all

  39. Cha'd says:

    Kindly help please, done all the setups without any error but from this step am getting “404 Not Found” Nginx

    Logon to your brandly new Nextcloud in your browser
    https://your.dedyn.io/login

    What i have missed?

    • Did you replace your.dedyn.io with your domain in the browser?

      • Cha'd says:

        Yes I did and i hav checked with local IP also it’s same. Have run the setup twice now all “https://your.dedyn.io/login” is replace by my nextcloud address.
        My loacal IP 192.168.x.221 router IP 192.168.x.201 which i set on “NGINX configuration(# resolver IP is your Router-IP (e.g. your FritzBox))” also did forward ports to reach outside my network and i can ping on my nextcloud address outside network.

        • please check the redis-, nginx-, php- and mysql logfiles. could you please issue curl https://your.dedyn.io and send me the result

          • Cha'd says:

            Here’s the out put of curl command, and i followed ur guide for ubuntu 16 it worked flawless but this one only giving problem. am not good with linux so didn’t no hot to check redis-, nginx-, php- and mysql logfiles.

            curl: (60) SSL certificate problem: self signed certificate
            More details here: https://curl.haxx.se/docs/sslcerts.html

            curl failed to verify the legitimacy of the server and therefore could not
            establish a secure connection to it. To learn more about this situation and
            how to fix it, please visit the web page mentioned above.

            Thank you for your support

          • Cha'd says:

            Hi, done fresh installation Ubuntu server with static IP n configured all the steps but now “403 forbidden” nginx and below curl command.

            301 Moved Permanently

            301 Moved Permanently
            nginx

            Thank you

  40. aytac says:

    exelent tutorial only must be incluide onlyoffice or collabora so it will be completed 🙂

  41. robbie says:

    Hi Carsten. What modifications do you have to make to this if you decide to forward 80 and 443 to non traditional ports on your router? Eg 80 to 3000 and 443 to 5000?

  42. Miko says:

    Hallo, am Ende der zweiten Zeile bei “Install Nextcloud silently” ist ein kleiner Fehler, oder sind die Quotes am Ende richtig ?
    […]–data-dir “/var/nc_data”‘
    Auch wenn ich mir noch selbst einen anderen Fehler eingebaut habe, tolles howto.
    Vielen Dank

    Miko

  43. Stefan says:

    Hallo, In den Paketquellen von Ubuntu 18.04 ist nginx bereits in der Version 1.14 enthalten. Das Hinzufügen der nginx-Repositories zu den Paketquellen ist nicht daher nicht mehr erforderlich.
    Gruß Stefan

    • Leider doch, da sonst die NGINX Konfiguration für das buffering/streaming (MP4-Module) nicht verfügbar wäre. Trotzdem danke!. Servus, Carsten

      • Stefan says:

        Hallo, vielen Dank, an MP4 hatte ich nicht gedacht.
        Ansonsten TOP Anleitung.
        Verwende ngnix Reverse-Proxy vHost, NC und WordPress. Da hat sich was was geändert.
        Vielen Dank
        Gruß Stefan

        • servus. was hat sich geändert?

          • Stefan says:

            Die vHost-Dateien von nginx werden nun in den Verzeichnissen sites-available und sites-enabled verwaltet. vHost, die bis Dato unter /etc/nginx/conf.d gespeichert waren, müssen nun im Verzeichnis /etc/nginx/sitesd-enabled untergebracht werden.

  44. RubberChicken says:

    Awesome – Have been using OwnCloud on Ubuntu 14.04 but wanted to make the leap to Ubuntu 18.04 and NextCloud. Am not a strong Linux admin (have MS focus) but have been able to successfully build myself a new up to date and secure system thanks to your guide. Really appreciate it!

  45. Daniel Atz says:

    Very good!
    I do not know why, but my Nextcloud takes about 5 or 10 seconds to login. Ever.

    • please have a look into mysql:
      database nextcloud, table oc_bruteforce_attempts.
      If your client is listed issue
      delete from oc_bruteforce_attempts;
      to purge entries.

  46. Robin says:

    I have followed the guide and it works.

    But I have one issue now, when I’m looking under loggs in the Nextcloud WebGUI I can see this:

    The “X-XSS-Protection” HTTP header is not set to “1; mode=block”. This is a potential security or privacy risk, as it is recommended to adjust this setting accordingly.
    The “X-Robots-Tag” HTTP header is not set to “none”. This is a potential security or privacy risk, as it is recommended to adjust this setting accordingly.
    The “X-Download-Options” HTTP header is not set to “noopen”. This is a potential security or privacy risk, as it is recommended to adjust this setting accordingly.
    The “X-Permitted-Cross-Domain-Policies” HTTP header is not set to “none”. This is a potential security or privacy risk, as it is recommended to adjust this setting accordingly.

    But my /etc/nginx/header.conf are correct.

    # add_header Strict-Transport-Security “max-age=15768000; includeSubDomains; preload;”;
    add_header X-Robots-Tag none;
    add_header X-Download-Options noopen;
    add_header X-Permitted-Cross-Domain-Policies none;
    # add_header X-Content-Type-Options “nosniff” always;
    add_header X-XSS-Protection “1; mode=block” always;
    add_header Referrer-Policy “same-origin” always;

    And the header is included in the /etc/nginx/nginx.conf

  47. Robin says:

    And also I do get this:

    Apr 28 14:26:48 nextcloud nginx[4230]: nginx: [emerg] unknown directive “mp4” in /etc/nginx/conf.d/nextcloud.conf:41
    Apr 28 14:26:48 nextcloud nginx[4230]: nginx: configuration file /etc/nginx/nginx.conf test failed
    Apr 28 14:26:48 nextcloud systemd[1]: nginx.service: Control process exited, code=exited status=1
    Apr 28 14:26:48 nextcloud systemd[1]: nginx.service: Failed with result ‘exit-code’.
    Apr 28 14:26:48 nextcloud systemd[1]: Failed to start A high performance web server and a reverse proxy server.

  48. Robin says:

    Perfect thanks,
    But 18.04 still just have openssl 1.1.0g I guess that we still should install openssl 1.1.0h as that’s newer?

  1. 26. June 2018

    […] Wer gerne seine eigene Lösung zur Speicherung und zur gemeinsamen Verwendung von Daten verwenden möchte, kann hier mit Nextcloud auf eine ziemlich gute und kostenfreie Lösung zurückgreifen. Dieser Beitrag zeigt, wie ich die Installation und die Konfiguration vorgenommen habe. Als Vorlage für die Installation habe ich den folgenden, sehr guten und ausführlichen (DANKE dafür an dieser Stelle!) genutzt: Nextcloud 13 installation guide (Ubuntu 18.04 LTS) […]

  2. 5. July 2018

    […] you Carsten for your excellent guide!  My goal here is to base my walk-through on his but also mention the “Gotchas!!” that […]

Leave a Reply

Your email address will not be published. Required fields are marked *