Nextcloud 13 installation guide (Ubuntu 18.04 LTS)


Following this guide you will be able to install and configure Nextcloud 13 based on Ubuntu 18.04 LTS, NGINX 1.14, openssl 1.1.0h, TLSv1.3, PHP 7.2, MariaDB, Redis, fail2ban, firewall (ufw) and will achieve an A+ rating from as well Nextcloud as 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, 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 Mini-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.4 LTS (64Bit).

Instructions regarding Nextcloud based on Ubuntu 16.04.4 LTS can be found here


Table of content

  1. Prepare your server and install NGINX
  2. PHP
  3. MariaDB
  4. Redis
  5. Nextcloud (SSL enabled, A+)
  6. fail2ban and firewall (ufw)

Last Updates:
May, 17th 2018

  • ammendment to the renewal cronjob

May, 3rd 2018:

April, 30th 2018:


Prepare your server and install NGINX

sudo -s
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 -y
apt install language-pack-en-base -y && sudo LC_ALL=en_US.UTF-8 add-apt-repository ppa:ondrej/php -y && apt update && apt upgrade -y
apt remove nginx nginx-common nginx-full -y --allow-change-held-packages
sed -i '$adeb http://nginx.org/packages/ubuntu/ xenial nginx' /etc/apt/sources.list
sed -i '$adeb-src http://nginx.org/packages/ubuntu/ xenial nginx' /etc/apt/sources.list
wget http://nginx.org/keys/nginx_signing.key && apt-key add nginx_signing.key
apt update && 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.2-fpm.sock;
}
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 192.168.2.1;
# resolver IP is your Router-IP (e.g. your FritzBox)
resolver_timeout 10s;
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

Install PHP

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

Awesome, PHP 7.2 is already installed.

Configure PHP:

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

Mount tmpfs and then restart both, PHP and NGINX:

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

MariaDB

apt update && apt install mariadb-server -y

Secure MariaDB:

mysql_secure_installation
Enter current password for root (enter for none): <ENTER>
Set root password? [Y/n] Y
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:

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

Change the entire my.cnf-file to:

[server]
skip-name-resolve
innodb_buffer_pool_size = 128M
innodb_buffer_pool_instances = 1
innodb_flush_log_at_trx_commit = 2
innodb_log_buffer_size = 32M
innodb_max_dirty_pages_pct = 90
query_cache_type = 1
query_cache_limit = 2M
query_cache_min_res_unit = 2k
query_cache_size = 64M
tmp_table_size= 64M
max_heap_table_size= 64M
slow-query-log = 1
slow-query-log-file = /var/log/mysql/slow.log
long_query_time = 1

[client-server]
!includedir /etc/mysql/conf.d/
!includedir /etc/mysql/mariadb.conf.d/

[client]
default-character-set = utf8mb4

[mysqld]
character-set-server = utf8mb4
collation-server = utf8mb4_general_ci
binlog_format = MIXED
innodb_large_prefix=on
innodb_file_format=barracuda
innodb_file_per_table=1

Restart and connect to MariaDB:

service mysql restart && mysql -uroot

Create the database and the user:

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;
quit;

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

Modify /etc/sysctl.conf and /etc/rc.local:

cp /etc/sysctl.conf /etc/sysctl.conf.bak && sed -i '$avm.overcommit_memory = 1' /etc/sysctl.conf

Reboot your server:

shutdown -r now

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;
#Your DDNS adress, (e.g. from desec.io or no-ip.com) 
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 ~ ^/(?: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|woff|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;
}
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|woff|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/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/fullchain.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 TLSv1.3;
ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!3DES:!MD5:!PSK:!AES128';
ssl_prefer_server_ciphers on;
ssl_ecdh_curve secp384r1;
ssl_stapling on;
ssl_stapling_verify on;

Androider’s: if you run in troubles e.g. using CalDAV/CardDAV please reduce the eliptic curve and cipher strength to:

ssl_ciphers 'ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS';
ssl_ecdh_curve prime256v1;

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;

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 "same-origin" always;

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 s/\#\ssl/\ssl/g /etc/nginx/ssl.conf && service nginx restart

Create a certificate renewal automatism:

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.2-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.2-fpm restart && service nginx restart

Adjust Nextcloud Apps

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.2-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.2-fpm restart && service redis-server restart && service nginx restart

and the message should disappear!


Optimize your Nextcloud using a script

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
chmod +x /root/optimize.sh

Issue the optimize.sh script once:

/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

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 lines:

[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

Re-start the fail2ban-service:

service fail2ban restart

Configure your ufw (uncomplicated firewall):

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

and 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

63 Responses

  1. 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

  2. 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

  3. 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 -

  4. 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.

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

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

  7. 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

          • Robin says:

            I did also notice that you have deleted the row:
            5 1 * * * php -f /var/www/nextcloud/occ files:scan-app-data > /dev/null 2>&1

            why’s that?

          • it is part of the optimize.sh and in roots crontab now.

          • Robin says:

            I did find out the issue with the (error) NOAUTH Authentication required it’s because that I did use the hashsecret PW for redis, so I just added -a MYSECRETPASSWORD to the file and it did work after that.

          • i guess, you forgot sudo -s prior issuing the script or redis pwd.

          • Robin says:

            Okej, so I can delete this row now?
            5 1 * * * php -f /var/www/nextcloud/occ files:scan-app-data > /dev/null 2>&1

          • yes, and add the row from the guide to root’s crontab

  8. 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

          • Hi, please provide me ssh access to your environemnt per mail and i will investigate further. cheers, carsten

          • 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

  9. aytac says:

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

  10. 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?

  11. 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

  12. 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.

          • Hallo Stefan. Man kann es so oder so machen, muss es aber nicht. Es hängt auch vom verwendeten NGINX ab. Danke u. servus, Carsten

  13. 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!

  14. 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.

  15. 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

  16. 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.

  17. 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?

Leave a Reply

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