Nextcloud 24/Ubuntu 20, multi instance setup

Sep 22, 2022
đź’ˇ
Work in Progress

Basic Setup

Some Basic Tools for Basic System Operation

apt-get install sudo wget curl unzip gnupg2 git apt-transport-https net-tools bash-completion -y
General Tools

Webserver Setup

Install Nginx Webserver

Why Nginx?
Sold, Easy to understand, lightweigt and used by millions

apt-get install nginx -y
Install Nginx

Setup Basic/Default Configuration

# make directory for certs and files
mkdir /etc/nginx/cert
# Generate DH Keys
openssl dhparam -out /etc/nginx/cert/dhparam.pem 4096
# Generate Default SSL Cert for default page
openssl req -new -newkey rsa:4096 -days 3650 -nodes -x509 -keyout /etc/nginx/cert/default.key -out /etc/nginx/cert/default.crt

# remove old default page
rm /etc/nginx/sites-available/default
Install Nginx

Create the Default Site File, the "return 444" returns no data to the client if the IP is accessed by IP or unknown Hostname. Less Traffic for the server to set to junk requests.

server {
        listen 80 default_server;
        listen [::]:80 default_server;
        server_name _;
        return 444;
        access_log  /var/log/nginx/default.access.log;
        error_log   /var/log/nginx/default.error.log;
}
server {
        listen 443 ssl default_server;
        listen [::]:443 ssl default_server;
        server_name _;
        ssl_certificate /etc/nginx/cert/default.crt;
        ssl_certificate_key /etc/nginx/cert/default.key;
        return 444;
        access_log  /var/log/nginx/default.access.log;
        error_log   /var/log/nginx/default.error.log;
}
nano /etc/nginx/sites-available/default

Link Default page to enabled sites.

ln -s /etc/nginx/sites-available/default /etc/nginx/sites-enabled/default

Set default SSL Settings to only secure options only, get's a high rating on SSL Scans. Be carefull with the preload option!

# SSL Settings
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:TLS_CHACHA20_POLY1305_SHA256;
ssl_prefer_server_ciphers on;
ssl_session_timeout  10m;
ssl_session_cache shared:SSL:10m;
ssl_session_tickets off;
# OCSP stapling
ssl_stapling on;
ssl_stapling_verify on;

ssl_dhparam /etc/nginx/cert/dhparam.pem;
ssl_ecdh_curve secp384r1;


resolver 1.1.1.1 1.0.0.1 valid=300s;
resolver_timeout 5s;

# HSTS Header (63072000 seconds)
# add_header Strict-Transport-Security 'max-age=63072000; includeSubDomains;';

# add_header X-Frame-Options "ALLOW-FROM domains";
# add_header Content-Security-Policy "frame-ancestors domains";
# add_header X-Content-Type-Options nosniff;
# add_header X-XSS-Protection "1; mode=block";
nano /etc/nginx/security.conf

Add this to the nginx config, for shorter timeouts and gzip for compression. Boost of Perfomance

server_tokens off;

gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_buffers 16 8k;
gzip_http_version 1.1;
gzip_min_length 256;
gzip_types
  application/atom+xml
  application/geo+json
  application/javascript
  application/x-javascript
  application/json
  application/ld+json
  application/manifest+json
  application/rdf+xml
  application/rss+xml
  application/xhtml+xml
  application/xml
  font/eot
  font/otf
  font/ttf
  image/svg+xml
  text/css
  text/javascript
  text/plain
  text/xml;


    client_body_buffer_size 10K;
    client_header_buffer_size 1k;
    client_max_body_size 8m;
    large_client_header_buffers 4 4k;


    client_body_timeout 10;
    client_header_timeout 10;
    keepalive_timeout 5 5;
    send_timeout 10;
nano /etc/nginx/nginx.conf

Restart Service and enable

systemctl restart nginx
systemctl enable nginx

PHP FPM and Modules

apt-get install php-fpm php-xml php-cli php-cgi php-mysql php-imap php-mbstring php-gd php-curl php-zip php-intl php-bcmath php-gmp php-imagick imagemagick php-bz2 php-json php-redis php-apcu php-opcache php-ldap -y
Installation of all modules

Adjust the PHP Config for caching/time and size settings

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

expose_php = Off
date.timezone = Europe/Berlin

upload_max_filesize = 2048M
post_max_size = 1024M
max_execution_time = 300
max_input_time = 60
memory_limit = 512M
nano /etc/php/7.4/fpm/php.ini

Add this to the CLI PHP File

apc.enable_cli = 1
nano /etc/php/7.4/cli/php.ini

Confirm Setting

zend_extension=opcache.so
nano /etc/php/7.4/fpm/conf.d/10-opcache.ini

Restart Service and enable

systemctl restart php7.4-fpm.service
systemctl enable php7.4-fpm.service

Database Setup

apt-get install mariadb-server mariadb-client -y
Installation of MariaDB as Mysql Server
mysql_secure_installation

# answer questions
# y-y-y-y and set password
# Login with root user
mysql -u root -p

Create a nextcloud database

CREATE DATABASE nextcloud CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
GRANT ALL PRIVILEGES ON nextcloud.* TO 'nextcloud'@'localhost' IDENTIFIED BY 'password';
FLUSH PRIVILEGES;
QUIT;

Redis

apt-get install redis-server -y
Installation of Redis Server
port 0
unixsocket /run/redis/redis-server.sock
unixsocketperm 770
nano /etc/redis/redis.conf

Add www-data user to redis group to allow access to redis-server.sock

usermod -a -G redis www-data

Restart Redis Service

systemctl restart redis
systemctl enable redis

Nextcloud Install

# Nextcloud Instance
wget https://download.nextcloud.com/server/releases/latest.zip -O nextcloud-latest.zip

mkdir /var/www/instance
unzip -q nextcloud-latest.zip -d /var/www/instance

chown -R www-data:www-data /var/www/instance
chmod -R 755 /var/www/instance

Nextcloud Nginx Config File

Upload the certificate to the right location, it is needed at this point

Create nginx file and adjust:

  • server_name
  • ssl_certificate
  • root
upstream php-handler {
    server unix:/var/run/php/php7.4-fpm.sock;
}

server {
    listen 80;
    listen [::]:80;
    server_name domain;

    # Enforce HTTPS
    return 301 https://$server_name$request_uri;
}
server {
    listen 443      ssl http2;
    listen [::]:443 ssl http2;
    server_name domain;
    include /etc/nginx/security.conf;
    ssl_certificate /etc/cert/server.cer;
    ssl_certificate_key /etc/cert/server.key;

    # Path to the root of your installation
    root /var/www/instance/nextcloud;
	
    # HSTS settings
    # WARNING: Only add the preload option once you read about
    # the consequences in https://hstspreload.org/. This option
    # will add the domain to a hardcoded list that is shipped
    # in all major browsers and getting removed from this list
    # could take several months.
    add_header Strict-Transport-Security "max-age=15768000; includeSubDomains;" always;

    # set max upload size
    client_max_body_size 512M;
    fastcgi_buffers 64 4K;

    # Enable gzip but do not remove ETag headers
    gzip on;
    gzip_vary on;
    gzip_comp_level 4;
    gzip_min_length 256;
    gzip_proxied expired no-cache no-store private no_last_modified no_etag auth;
    gzip_types application/atom+xml application/javascript application/json application/ld+json application/manifest+json application/rss+xml application/vnd.geo+json application/vnd.ms-fontobject application/x-font-ttf application/x-web-app-manifest+json application/xhtml+xml application/xml font/opentype image/bmp image/svg+xml image/x-icon text/cache-manifest text/css text/plain text/vcard text/vnd.rim.location.xloc text/vtt text/x-component text/x-cross-domain-policy;

    # Pagespeed is not supported by Nextcloud, so if your server is built
    # with the `ngx_pagespeed` module, uncomment this line to disable it.
    #pagespeed off;

    # HTTP response headers borrowed from Nextcloud `.htaccess`
    add_header Referrer-Policy                      "no-referrer"   always;
    add_header X-Content-Type-Options               "nosniff"       always;
    add_header X-Download-Options                   "noopen"        always;
    add_header X-Frame-Options                      "SAMEORIGIN"    always;
    add_header X-Permitted-Cross-Domain-Policies    "none"          always;
    add_header X-Robots-Tag                         "none"          always;
    add_header X-XSS-Protection                     "1; mode=block" always;

    # Remove X-Powered-By, which is an information leak
    fastcgi_hide_header X-Powered-By;



    # Specify how to handle directories -- specifying `/index.php$request_uri`
    # here as the fallback means that Nginx always exhibits the desired behaviour
    # when a client requests a path that corresponds to a directory that exists
    # on the server. In particular, if that directory contains an index.php file,
    # that file is correctly served; if it doesn't, then the request is passed to
    # the front-end controller. This consistent behaviour means that we don't need
    # to specify custom rules for certain paths (e.g. images and other assets,
    # `/updater`, `/ocm-provider`, `/ocs-provider`), and thus
    # `try_files $uri $uri/ /index.php$request_uri`
    # always provides the desired behaviour.
    index index.php index.html /index.php$request_uri;

    # Rule borrowed from `.htaccess` to handle Microsoft DAV clients
    location = / {
        if ( $http_user_agent ~ ^DavClnt ) {
            return 302 /remote.php/webdav/$is_args$args;
        }
    }
    location = /robots.txt {
        allow all;
        log_not_found off;
        access_log off;
    }
    # Make a regex exception for `/.well-known` so that clients can still
    # access it despite the existence of the regex rule
    # `location ~ /(\.|autotest|...)` which would otherwise handle requests
    # for `/.well-known`.

   location ^~ /.well-known {
        # The following 6 rules are borrowed from `.htaccess`

        location = /.well-known/carddav     { return 301 /remote.php/dav/; }
        location = /.well-known/caldav      { return 301 /remote.php/dav/; }
        # Anything else is dynamically handled by Nextcloud
        location ^~ /.well-known            { return 301 /index.php$uri; }

        try_files $uri $uri/ =404;
    }
    # Rules borrowed from `.htaccess` to hide certain paths from clients
    location ~ ^/(?:build|tests|config|lib|3rdparty|templates|data)(?:$|/)  { return 404; }
    location ~ ^/(?:\.|autotest|occ|issue|indie|db_|console)              { return 404; }

    # Ensure this block, which passes PHP files to the PHP process, is above the blocks
    # which handle static assets (as seen below). If this block is not declared first,
    # then Nginx will encounter an infinite rewriting loop when it prepends `/index.php`
    # to the URI, resulting in a HTTP 500 error response.
    location ~ \.php(?:$|/) {
        fastcgi_split_path_info ^(.+?\.php)(/.*)$;
        set $path_info $fastcgi_path_info;

        try_files $fastcgi_script_name =404;

        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param PATH_INFO $path_info;
        fastcgi_param HTTPS on;

        fastcgi_param modHeadersAvailable true;         # Avoid sending the security headers twice
        fastcgi_param front_controller_active true;     # Enable pretty urls
        fastcgi_pass php-handler;

        fastcgi_intercept_errors on;
        fastcgi_request_buffering off;
    }

    location ~ \.(?:css|js|svg|gif)$ {
        try_files $uri /index.php$request_uri;
        expires 6M;         # Cache-Control policy borrowed from `.htaccess`
        access_log off;     # Optional: Don't log access to assets
    }

    location ~ \.woff2?$ {
        try_files $uri /index.php$request_uri;
        expires 7d;         # Cache-Control policy borrowed from `.htaccess`
        access_log off;     # Optional: Don't log access to assets
    }

    location / {
        try_files $uri $uri/ /index.php$request_uri;
    }
}
nano /etc/nginx/sites-available/cloud

Reload the Nginx Service, then visit the Website under the domain that was setup. Setup the Database and adjust other settings during the initial setup. That will generate a config.php file in the directory of the instance.

Nextcloud Cron Setup

# Edit Cronjob for www-data user
crontab -u www-data -e

# Add following line (adjust for your path)
*/5  *  *  *  * php -f /var/www/instance/nextcloud/cron.php

Nextcloud Config File

# Costum Config, add after last line off existing config

  'simpleSignUpLink.shown' => false,
  'lost_password_link' => 'disabled',
  'auth.webauthn.enabled' => false,
  'default_language' => "de",
  'force_language' => "de",
  "default_locale" => "de_DE",
  "force_locale" => "de_DE",
  'default_phone_region' => 'DE',
  'skeletondirectory' => '',
  'knowledgebaseenabled' => false,
  'defaultapp' => 'files',
  'allow_user_to_change_display_name' => false,
  'profile.enabled' => false,
  'filelocking.enabled' => true,
  'memcache.local' => '\OC\Memcache\APCu',
  'memcache.distributed' => '\OC\Memcache\Redis',
  'memcache.locking' => '\OC\Memcache\Redis',
  'redis' => [
       'host'     => '/run/redis/redis-server.sock',
       'port'     => 0,
       'dbindex'  => 0,
       'timeout'  => 1.5,
  ],
nano /var/www/instance/nextcloud/config/config.php

Nextcloud Remove Apps

# Set Path Variable for Easier spam
$path = /var/www/instance/nextcloud/occ

# Test OCC Command
sudo -u www-data php $path
# List all Apps
sudo -u www-data php $path app:list

sudo -u www-data php $path app:disable activity
sudo -u www-data php $path app:disable circles
sudo -u www-data php $path app:disable comments
sudo -u www-data php $path app:disable contactsinteraction
sudo -u www-data php $path app:disable dashboard
sudo -u www-data php $path app:disable federation
sudo -u www-data php $path app:disable firstrunwizard
sudo -u www-data php $path app:disable nextcloud_announcements
sudo -u www-data php $path app:disable notifications
sudo -u www-data php $path app:disable recommendations
sudo -u www-data php $path app:disable support
sudo -u www-data php $path app:disable systemtags
sudo -u www-data php $path app:disable survey_client
sudo -u www-data php $path app:disable updatenotification
sudo -u www-data php $path app:disable user_status
sudo -u www-data php $path app:disable weather_status


sudo -u www-data php $path app:enable theming_customcss
sudo -u www-data php $path app:enable twofactor_totp
sudo -u www-data php $path app:enable external

Nextcloud Costum CSS

#body-login, #firstrunwizard .firstrunwizard-header, #theming-preview {
  background-size: contain;
}
form {
    margin: 80px 0px 0px 0px;
}
#app-settings-header .settings-button {
    display: none;
}

That's it, enjoy a solid setup nextcloud instance with some clutter removed, the settings on the plattform are not descriped fully here, but this is self preference. Also the config.php is heavily costumised.