This document is a WORK IN PROGRESS.
This is just a quick personal cheat sheet: treat its contents with caution!
Nextcloud (with PostgreSQL, Redis and Nginx) on Gentoo¶
Prerequisite(s)
Reference(s)
- https://docs.nextcloud.com/
- https://www.c-rieger.de/nextcloud-installation-guide-ubuntu/
- https://www.c-rieger.de/nextcloud-16-installation-guide-debian-apache2/
- https://wiki.archlinux.org/index.php/Nextcloud#PostgreSQL
- https://draculaservers.com/tutorials/install-nextcloud-nginx-ubuntu/
- https://bayton.org/docs/nextcloud/installing-nextcloud-on-ubuntu-16-04-lts-with-redis-apcu-ssl-apache/
- https://www.linuxtricks.fr/wiki/installer-nextcloud-sur-gentoo-ou-calculate-linux
- https://help.nextcloud.com/t/postgresql-nextcloud/1083
- https://www.youtube.com/watch?v=EbD1hFzJtls ?
Table of contents¶
- Install
- Nextcloud packages in world set
- Config
- Initialize Nextcloud
- Logs
fail2ban
- Cron
- ! WIP !
rsync
backup script to run with Cron - External storages
- Configure a VPN to accept traffic from public IP and respond on the same channel
davfs2
ufw
- ! WIP ! Import Bitwarden passwords into Nextcloud Passwords app
- Procedures
- Troubleshooting
- TODO
Install¶
Install Nextcloud:
# vi /etc/portage/package.accept_keywords
> # (manual) last nextcloud
> www-apps/nextcloud
>
> ...
# vi /etc/portage/package.use/nextcloud
> ...
> www-apps/nextcloud -sqlite
> www-apps/nextcloud postgres
> www-apps/nextcloud vhosts
> ...
# emerge -a nexcloud
# webapp-config -h yourhostname.duckdns.org -d nextcloud -I nextcloud xx.x.x
# chown -R nginx:nginx /var/www/yourhostname.duckdns.org
Then make sure that all prerequisites packages are installed and configured.
Nextcloud packages in world set¶
Make sure your current major Nextcloud packages won't be overwritten by accident in an upcoming update (e.g. with those packages at those versions):
# emerge -av --noreplace www-apps/nextcloud:18.0.0
# emerge -av --noreplace dev-lang/php:7.3
?# emerge -av --noreplace www-servers/nginx:1.16.1-r1
?# emerge -av --noreplace dev-db/redis:5.0.7
# emerge -av --noreplace dev-db/postgresql:12
# vi /var/lib/portage/world # check your current nextcloud packages versions in the world file:
> ...
> www-apps/nextcloud
> www-apps/nextcloud:18.0.0
> ...
> dev-lang/php
> dev-lang/php:7.3
> ...
> www-servers/nginx
> www-servers/nginx:1.16.1-r1
> ...
> dev-db/redis
> dev-db/redis:5.0.7
> ...
> dev-db/postgresql
> dev-db/postgresql:12
> ...
After properly updating one of those packages (see "Nextcloud update procedure" section near the
end of this file), don't forget to update the /var/lib/portage/world
file accordingly.
Domain name and router configuration¶
Warning
Getting a domain name is optional, but recommended if you don't want to enter your server's public IP address every time you want to access your Nextcloud server, or if you don't have a fixed public IP address.
Warning
Configuring your router in order to forward your port 80 and port 443 is optional, but recommended if you want to access your Nextcloud server outside your local network.
You can refer to DuckDNS for a free and open source service which will
point a DNS (sub domains of yourhostname.duckdns.org
Tip
You might want to check if your router does support NAT loopback (see https://en.wikipedia.org/wiki/Network_address_translation#NAT_hairpinning and see https://en.wikipedia.org/wiki/Hairpinning). If it doesn't, you will have to look for a work around in order to access your server by it's domain name from your local network.
Config¶
PostgreSQL Configuration¶
Create the Nextcloud user and Nextcloud database:
$ su - postgres # enter postgres pwd
$ createuser -h localhost -P nextcloud # enter nextcloud pwd, confirm pwd & enter postgres pwd
$ createdb -O nextcloud nextcloud # and enter postgres pwd
$ exit
$ exit
TODO: PostgreSQL optimization:
APCu and Redis config (Memory caching config)¶
Reference(s)
Configure Redis:
# cp /etc/redis.conf /etc/redis.conf.bak
# vi /etc/redis.conf
> ...
> #port 6379
> port 0
> ...
> # unixsocket /tmp/redis.sock
> # unixsocketperm 700
>
> # Enable and update the Redis socket path:
> unixsocket /run/redis/redis.sock
> # Set permission to all members of the redis user group:
> unixsocketperm 770
> ...
> #maxclients 10000
> maxclients 512
> ...
Add the Nginx user to the Redis group (Nginx should logout and log back in for this change to takes effect, or just reboot):
Add APCu support for user cache:
Make sure you are building pecl-apcu
against the right PHP version:
If pecl-apcu
is not built against the right PHP version (e.g. v7.2
instead of v7.3
):
$ sudo vi /etc/portage/package.use/pecl
> dev-php/pecl-apcu -php_targets_php7-2
> dev-php/pecl-apcu php_targets_php7-3
$ sudo emerge -a dev-php/pecl-apcu
Enable APC in php.ini
:
# vi /etc/php/fpm-phpX.X/php.ini
> ...
> ; Misc
>
> ; APCu is disabled by default on CLI which could cause issues with nextcloud’s
> ; cron jobs. Enabling it:
> apc.enable_cli = 1
Configure Nextcloud to use Redis:
# vi /var/www/yourhostname.duckdns.org/htdocs/nextcloud/config/config.php
> ...
> 'memcache.local' => '\OC\Memcache\APCu', # and not '\\OC\\Memcache\\APCu' ?
> 'memcache.locking' => '\OC\Memcache\Redis', # and not '\\OC\\Memcache\\Redis' ?
> 'redis' => [
> 'host' => '/var/run/redis/redis.sock',
> 'port' => 0,
> ],
Optimize Redis:
# vi /etc/sysctl.conf
> ...
> # Fix Redis low memory condition warning:
> vm.overcommit_memory = 1
> # Fix Redis TCP backlog setting warning:
> net.core.somaxconn=65535
Nginx config¶
Configure Nginx according to the Nextcloud manual: https://docs.nextcloud.com/server/stable/admin_manual/installation/nginx.html.
For example, here is my /etc/nginx/nginx.conf
(default configuration):
> user nginx nginx;
> worker_processes auto;
>
> error_log /var/log/nginx/error_log info;
>
> events {
> worker_connections 1024;
> use epoll;
> }
>
> http {
> include /etc/nginx/mime.types;
> default_type application/octet-stream;
>
> log_format main
> '$remote_addr - $remote_user [$time_local] '
> '"$request" $status $bytes_sent '
> '"$http_referer" "$http_user_agent" '
> '"$gzip_ratio"';
>
> client_header_timeout 10m;
> client_body_timeout 10m;
> send_timeout 10m;
>
> connection_pool_size 256;
> client_header_buffer_size 1k;
> large_client_header_buffers 4 2k;
> request_pool_size 4k;
>
> gzip off;
>
> output_buffers 1 32k;
> postpone_output 1460;
>
> sendfile on;
> tcp_nopush on;
> tcp_nodelay on;
>
> keepalive_timeout 75 20;
>
> ignore_invalid_headers on;
>
> index index.html;
>
> #include /etc/nginx/conf.d/*.conf;
> include /etc/nginx/conf.d/nextcloud.conf;
> }
And here is my /etc/nginx/conf.d/nextcloud.conf
(default configuration):
> # https://docs.nextcloud.com/server/stable/admin_manual/installation/nginx.html?highlight=nginx
>
> upstream php-handler {
> server 127.0.0.1:9000;
> #server unix:/var/run/php-fpm/php-fpm.sock;
> }
>
> server {
> listen 80;
> listen [::]:80;
> server_name yourhostname.duckdns.org;
> # enforce https
> return 301 https://$server_name:443$request_uri;
> }
>
> server {
> listen 443 ssl http2;
> listen [::]:443 ssl http2;
> server_name yourhostname.duckdns.org;
>
> # Use Mozilla's guidelines for SSL/TLS settings
> # https://mozilla.github.io/server-side-tls/ssl-config-generator/
> # NOTE: some settings below might be redundant
>
> # ssl_certificate /etc/ssl/path/to/your/cert.crt
> # ssl_certificate_key /etc/ssl/path/to/your/key.key
>
> # Add headers to serve security related headers
> # Before enabling Strict-Transport-Security headers please read into this
> # topic first.
> #add_header Strict-Transport-Security "max-age=15768000; includeSubDomains; preload;";
> #
> # 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 X-Content-Type-Options nosniff;
> add_header X-XSS-Protection "1; mode=block";
> add_header X-Robots-Tag none;
> add_header X-Download-Options noopen;
> add_header X-Permitted-Cross-Domain-Policies none;
> add_header Referrer-Policy no-referrer;
> add_header X-Frame-Options "SAMEORIGIN";
>
> # Remove X-Powered-By, which is an information leak
> fastcgi_hide_header X-Powered-By;
>
> # Path to the root of your installation
> root /var/www/yourhostname.duckdns.org/htdocs/nextcloud/;
>
> location = /robots.txt {
> allow all;
> log_not_found off;
> access_log off;
> }
>
> # The following 2 rules are only needed for the user_webfinger app.
> # Uncomment it if you're planning to use this app.
> #rewrite ^/.well-known/host-meta /public.php?service=host-meta last;
> #rewrite ^/.well-known/host-meta.json /public.php?service=host-meta-json last;
>
> # The following rule is only needed for the Social app.
> # Uncomment it if you're planning to use this app.
> #rewrite ^/.well-known/webfinger /public.php?service=webfinger last;
>
> location = /.well-known/carddav {
> return 301 $scheme://$host:$server_port/remote.php/dav;
> }
> location = /.well-known/caldav {
> return 301 $scheme://$host:$server_port/remote.php/dav;
> }
>
> # 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/manif est+json application/rss+xml application/vnd.geo+json application/vnd.ms-fontobject application/x-font-ttf applic ation/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 tex t/x-cross-domain-policy;
>
> # Uncomment if your server is build with the ngx_pagespeed module
> # This module is currently not supported.
> #pagespeed off;
>
> location / {
> rewrite ^ /index.php$request_uri;
> }
>
> location ~ ^\/(?:build|tests|config|lib|3rdparty|templates|data)\/ {
> deny all;
> }
> location ~ ^\/(?:\.|autotest|occ|issue|indie|db_|console) {
> deny all;
> }
>
> location ~ ^\/(?:index|remote|public|cron|core\/ajax\/update|status|ocs\/v[12]|updater\/.+|oc[ms]-provider\/. +)\.php(?:$|\/) {
> fastcgi_split_path_info ^(.+?\.php)(\/.*|)$;
> include fastcgi_params;
> fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
> fastcgi_param PATH_INFO $fastcgi_path_info;
> fastcgi_param HTTPS on;
> # Avoid sending the security headers twice
> fastcgi_param modHeadersAvailable true;
> # Enable pretty urls
> fastcgi_param front_controller_active true;
> fastcgi_pass php-handler;
> fastcgi_intercept_errors on;
> fastcgi_request_buffering off;
> }
>
> location ~ ^\/(?:updater|oc[ms]-provider)(?:$|\/) {
> try_files $uri/ =404;
> index index.php;
> }
>
> # Adding the cache control header for js, css and map files
> # Make sure it is BELOW the PHP block
> location ~ \.(?:css|js|woff2?|svg|gif|map)$ {
> try_files $uri /index.php$request_uri;
> add_header Cache-Control "public, max-age=15778463";
> # Add headers to serve security related headers (It is intended to
> # have those duplicated to the ones above)
> # Before enabling Strict-Transport-Security headers please read into
> # this topic first.
> #add_header Strict-Transport-Security "max-age=15768000; includeSubDomains; preload;";
> #
> # 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 X-Content-Type-Options nosniff;
> add_header X-XSS-Protection "1; mode=block";
> add_header X-Robots-Tag none;
> add_header X-Download-Options noopen;
> add_header X-Permitted-Cross-Domain-Policies none;
> add_header Referrer-Policy no-referrer;
> add_header X-Frame-Options "SAMEORIGIN";
>
> # Optional: Don't log access to assets
> access_log off;
> }
>
> location ~ \.(?:png|html|ttf|ico|jpg|jpeg)$ {
> try_files $uri /index.php$request_uri;
> # Optional: Don't log access to other assets
> access_log off;
> }
> }
php-pfm
config¶
Configure php-pfm
in order to work with the environment variables and Nginx:
# vi /etc/php/fpm-phpx.x/fpm.d/www.conf # uncomment env variables:
> ...
> ; Unix user/group of processes
> ; Note: The user is mandatory. If the group is not set, the default user's group
> ; will be used.
> user = nginx
> group = nginx
>...
> env[HOSTNAME] = $HOSTNAME
> env[PATH] = /usr/local/bin:/usr/bin:/bin
> env[TMP] = /tmp
> env[TMPDIR] = /tmp
> env[TEMP] = /tmp
> ...
Increase the PHP memory limit:
# vi /etc/php/fpm-phpX.X/php.ini
> ; Maximum amount of memory a script may consume (128MB)
> ; http://php.net/memory-limit
> memory_limit = 2048M
Enable OPcache:
# vi /etc/php/fpm-phpX.X/php.ini
> ...
> [opcache]
> ; Determines if Zend OPCache is enabled
> opcache.enable=1
>
> ; Determines if Zend OPCache is enabled for the CLI version of PHP
> opcache.enable_cli=1
>
> ; The OPcache shared memory storage size.
> ;opcache.memory_consumption=128
>
> ; The amount of memory for interned strings in Mbytes.
> opcache.interned_strings_buffer=8
>
> ; The maximum number of keys (scripts) in the OPcache hash table.
> ; Only numbers between 200 and 1000000 are allowed.
> opcache.max_accelerated_files=10000
>
> ; The maximum percentage of "wasted" memory until a restart is scheduled.
> ;opcache.max_wasted_percentage=5
>
> ; When this directive is enabled, the OPcache appends the current working
> ; directory to the script key, thus eliminating possible collisions between
> ; files with the same name (basename). Disabling the directive improves
> ; performance, but may break existing applications.
> ;opcache.use_cwd=1
>
> ; When disabled, you must reset the OPcache manually or restart the
> ; webserver for changes to the filesystem to take effect.
> ;opcache.validate_timestamps=1
>
> ; How often (in seconds) to check file timestamps for changes to the shared
> ; memory storage allocation. ("1" means validate once per second, but only
> ; once per request. "0" means always validate)
> opcache.revalidate_freq=1
>
> ; Enables or disables file search in include_path optimization
> ;opcache.revalidate_path=0
>
> ; If disabled, all PHPDoc comments are dropped from the code to reduce the
> ; size of the optimized code.
> opcache.save_comments=1
> ...
Install PHP extension for interfacing with Redis:
Install imagick
recommended PHP modules (for improved performance and better compatibility), and
make sure it's built against the right PHP version:
If pecl-imagick
is not build against the right version of PHP (e.g. 7.2 instead of 7.3):
$ sudo vi /etc/portage/package.use/pecl
> ...
> dev-php/pecl-imagick -php_targets_php7-2
> dev-php/pecl-imagick php_targets_php7-3
# emerge -a dev-php/pecl-imagick
Basic SSL certs config¶
Create basic self signed SSL certificate and key:
# mkdir /etc/ssl/nextcloud
# openssl req -x509 -nodes -days 9999 -newkey rsa:2048 -keyout /etc/ssl/nextcloud/yourhostname.key -out /etc/ssl/nextcloud/yourhostname.crt
Add the SSL cert and key to the Nginx Nextcloud configuration:
# vi /etc/nginx/conf.d/nextcloud.conf
> ...
> # Use Mozilla's guidelines for SSL/TLS settings
> # https://mozilla.github.io/server-side-tls/ssl-config-generator/
> # NOTE: some settings below might be redundant
>
> ssl_certificate /etc/ssl/nextcloud/yourhostname.crt;
> ssl_certificate_key /etc/ssl/nextcloud/yourhostname.key;
> ...
Test your configuration:
# nginx -t # test the nginx config
# rc-service postgresql-x.x restart
# rc-service nginx restart
# rc-service php-fpm restart
Now open a web browser and navigate to www.yourhostname.duckdns.org
.
Advanced SSL certs config¶
Install acme
and request ssl-certificates
:
# emerge -a acme-tiny
# mkdir /var/www/yourhostname.duckdns.org/acme-challenge/
# chown -R nginx:nginx /var/www/yourhostname.duckdns.org/acme-challenge
# mkdir /var/lib/letsencrypt
# cd /var/lib/letsencrypt
# openssl genrsa 4096 > account.key
# openssl genrsa 4096 > domain.key
# openssl req -new -sha256 -key domain.key -subj "/CN=yourhostname.duckdns.org" > domain.csr
# vi /etc/nginx/conf.d/nextcloud.conf # add acm-challenge location and turn off https
> ...
> # server {
> # listen 80;
> # listen [::]:80;
> # server_name yourhostname.duckdns.org;
> #
> # # enforce https
> # return 301 https://$server_name:443$request_uri;
> # }
>
> server {
> # listen 443 ssl http2;
> # listen [::]:443 ssl http2;
> listen 80;
> listen [::]:80;
> server_name yourhostname.duckdns.org;
>
> location ^~ /.well-known/acme-challenge/ {
> alias /var/www/yourhostname.duckdns.org/acme-challenge/;
> try_files $uri =404;
> }
> ...
# rc-service nginx restart
$ sudo -i
# acme-tiny --account-key /var/lib/letsencrypt/account.key --csr /var/lib/letsencrypt/domain.csr --acme-dir /var/www/yourhostname.duckdns.org/acme-challenge/ > /var/lib/letsencrypt/signed_chain.crt
# exit
# cp /var/lib/letsencrypt/signed_chain.crt /var/lib/letsencrypt/signed_chain.crt.back # backup signed_chain.crt just in case
# openssl dhparam -out dhparam4096.pem 4096
# vi /etc/nginx/conf.d/nextcloud.conf # turn https back on and ssl certs
> ...
> server {
> listen 80;
> listen [::]:80;
> server_name yourhostname.duckdns.org;
>
> location ^~ /.well-known/acme-challenge/ {
> alias /var/www/yourhostname.duckdns.org/acme-challenge/;
> try_files $uri =404;
> }
>
> # enforce https
> return 301 https://$server_name:443$request_uri;
> }
>
> server {
> listen 443 ssl http2;
> listen [::]:443 ssl http2;
>
> # Use Mozilla's guidelines for SSL/TLS settings
> # https://mozilla.github.io/server-side-tls/ssl-config-generator/
> # NOTE: some settings below might be redundant
>
> #ssl_certificate /etc/ssl/nextcloud/yourhostname.crt;
> #ssl_certificate_key /etc/ssl/nextcloud/yourhostname.key;
>
> ssl_certificate /var/lib/letsencrypt/signed_chain.crt;
> ssl_certificate_key /var/lib/letsencrypt/domain.key;
>
> ssl_session_timeout 1d;
> ssl_session_cache shared:MozSSL:10m;
> ssl_session_tickets off;
>
> ssl_dhparam /var/lib/letsencrypt/dhparam4096.pem;
>
> ssl_protocols TLSv1.2 TLSv1.3;
> ssl_ciphers ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA;
> ssl_prefer_server_cipher on;
>
> # Add headers to serve security related headers
> # Before enabling Strict-Transport-Security headers please read into this
> # topic first.
> #add_header Strict-Transport-Security "max-age=15768000; includeSubDomains; preload;";
>
> add_header Strict-Transport-Security "max-age=15768000; includeSubDomains" always;
>
> ...
>
> # Adding the cache control header for js, css and map files
> # Make sure it is BELOW the PHP block
> location ~ \.(?:css|js|woff2?|svg|gif|map)$ {
> try_files $uri /index.php$request_uri;
> add_header Cache-Control "public, max-age=15778463";
> # Add headers to serve security related headers (It is intended to
> # have those duplicated to the ones above)
> # Before enabling Strict-Transport-Security headers please read into
> # this topic first.
> #add_header Strict-Transport-Security "max-age=15768000; includeSubDomains; preload;";
> add_header Strict-Transport-Security "max-age=15768000; includeSubDomains" always;
> ...
# rc-service nginx restart
With the previous configurations, you should get A+ grades.
Auto renew certificates Cron job config¶
# vi /opt/renew_cert.sh
> #!/bin/sh
>
> rm -f /var/lib/letsencrypt/signed_chain.crt.tmp
>
> acme-tiny --disable-check --account-key /var/lib/letsencrypt/account.key --csr /var/lib/letsencrypt/domain.csr --acme-dir /var/www/yourhostname.duckdns.org/acme-challenge/ > /var/lib/letsencrypt/signed_chain.crt.tmp || exit
>
> mv -f /var/lib/letsencrypt/signed_chain.crt.tmp /var/lib/letsencrypt/signed_chain.crt
> rc-service nginx reload
# chmod 700 /opt/renew_cert.sh
[!] Note that this script won't work if the current certificate is already expired! [!]
$ sudo EDITOR=vi crontab -e # edit the crontab of the root user
> ...
> 0 0 1 * * /opt/renew_cert.sh 2>> /var/log/acme-tiny.log # runs once per month
Initialize Nextcloud¶
Navigate to youhostname.duckdns.org
in a browser. The first time, you will have a few fields to
configure:
- admin account name:
admin
-
admin account password:
adminpwd
-
data folder:
/media/raid/nextcloud-data
-
db user name:
nextcloud
- db user password (see Nextcloud user):
nextcloudpwd
- db name:
nextcloud
- db location (default port of PostgreSQL):
localhost:5432
Now Nextcloud is initializing and will soon be accessible.
Logs¶
Make sure logs are active, if there is no /var/log/nextcloud.log
file, run:
# touch /var/log/nextcloud.log
# chown nginx:nginx /var/log/nextcloud.log
# vi /var/www/gentoocloud.duckdns.org/htdocs/nextcloud/config/config.php
> <?php
> $CONFIG = array (
> ...
>
> 'logfile' => '/var/log/nextcloud.log',
> 'loglevel' => 1,
> 'logtimezone' => 'Europe/Paris',
> 'log_rotate_size' => 104857600,
>
> ...
> );
fail2ban
¶
Create a fail2ban Nextcloud filter:
# vi /etc/fail2ban/filter.d/nextcloud.conf
> [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
> [nextcloud]
> backend = auto
> enabled = true
> port = 80,443
> protocol = tcp
> filter = nextcloud
> maxretry = 3
> bantime = 36000
> findtime = 36000
> logpath = /var/log/nextcloud.log
>
> [nginx-http-auth]
> enabled = true
Restart the fail2ban service:
Cron¶
Nextcloud requires scheduled execution of some tasks, and by default it archives this by using AJAX, however AJAX is the least reliable method, and it is recommended to use Cron instead.
Create a job for the Nginx user:
# crontab -u nginx -e
> */5 * * * * php -f /var/www/yourhostname.duckdns.org/htdocs/nextcloud/cron.php
Check that everything is set by running:
! WIP ! rsync
backup script to run with Cron¶
This script will backup your Nextcloud data directory in /media/backup/nextcloud-backup
(if available, i.e. if a disk is mounted on /media/backup
):
TODO
External storages¶
One can add external storages to Nextcloud. For example, a local folder that might be shared between the server and Nextcloud.
First create a directory on your server that will be shared with Nextcloud, e.g.:
Then create a local external storage in Nextcloud. To do so:
- connect to the Nextcloud web client (with admin permissions)
- open the top right user menu
- select "Apps"
- select "Disabled apps" in the left menu
- enable the "External storages" app
- open the top right user menu again
- select "Settings"
- select "External storages" in the left menu
- finally create a local external storage (e.g. Folder name:
nextcloud-media
, External storage: "Local", Authentication: "None", Configuration:/media/raid/nextcloud-media
, Available for: "All users..."
Configure a VPN to accept traffic from public IP and respond on the same channel¶
See ProtonVPN cheat sheet (this tips should work with most VPNs, not only ProtonVPN).
NOTE: if the following error shows up: PR_END_OF_FILE_ERROR
, when trying to access your Nextcloud
instance, just restart it.
davfs2
¶
You can mount your Nextcloud using WebDAV with davfs2
.
- See https://wiki.archlinux.org/index.php/Nextcloud#Mounting_files_with_davfs2
- See https://wiki.archlinux.org/index.php/Davfs2
E.g.:
$ sudo mount -t davfs https://yourhostname.duckdns.org/remote.php/dav/files/NextUserName/ ~/nextcloud/NextUserName -o uid="linux-username",gid="linux-username",rw
Install, config and use¶
See https://docs.nextcloud.com/server/18/user_manual/files/access_webdav.html
A correct kernel config is needed:
> -> File systems
> -> Network File Systems # Symbol: NETWORK_FILESYSTEMS [=y])
> <*> Coda file system support (advanced network fs) # Symbol: CODA_FS [=y]
Warning
After configuring the kernel don't forget to do a kernel make and rebuild!
Install davfs2
:
Add your user to the davfs2
group:
Now you can mount your Nextcloud with davfs
:
$ mkdir -p ~/dav
$ sudo mount -t davfs https://yourhostname.duckdns.org/remote.php/dav/files/Nextcloud-User-Name/ ~/dav -o uid="linux-user",gid="linux-user",rw
ufw
¶
See ufw
TODO
! WIP ! Import Bitwarden passwords into Nextcloud Passwords app¶
In your Bitwarden settings -> "export vault" -> .csv
-> "submit"
You should now have a bitwarden_export_date.csv
file.
The Nextcloud escape character will be \
(backslash), but there is no such thing like escape
character in the Bitwarden CSV, so one shall escape every backslash that is already in the
bitwarden_export_date.csv
file (with another backslash):
The quote character will be "'" (simple quote), but there no such thing like quote character in the Bitwarden CSV, so one shall escape every quote character (with a backslash):
The default Bitwarden field delimiter is the comma "," and Bitwarden does not escape the field delimiter, so one might have to unescaped field delimiter in passwords.The following Vim commands will escape the delimiters contained in passwords:
:%s/.*\zs,/TEMP_FIELD_DELIMITER/ " replace every last ',' of each line by a temp delimiter
:%s/,/TEMP_FIELD_DELIMITER/ "
7@: " replace every 8 first ',' of each line by a temp delimiter
" because by default there should be 9 delimiters per line
:%s/,/\\,/g " escape every remaining ',' with a backslash in order to avoid
:%s/TEMP_FIELD_DELIMITER/,/g " set the new delimiter to ','
FIX ME: I just realized that there might be unescaped delimiter in notes too, not just passwords...
FIX ME: So I think would better write a real script to solve this...
In Nextcloud Passwords app -> "More" (`+` button) -> "Backup and Restore" -> "Restore or Import"
-> "1. Choose Format: Other/Custom CSV"
-> "2. Select File:
CSV Options
Line Break: Windows (CRLF, \r\n)
Field Delimiter: Detect
Quote Character: Single Quote
Escpae Character: Backslash"
-> Do not check "Detect unescaped quotes"
-> "Browse" and select the bitwarden_export_date.csv file
-> "3. Select Options
...
Procedures¶
Nextcloud trigger maintenance¶
$ sudo -u nginx php /var/www/yourhostname.duckdns.org/htdocs/nextcloud/occ maintenance:mode --on
$ sudo -u nginx php /var/www/yourhostname.duckdns.org/htdocs/nextcloud/occ maintenance:mode --off
Nextcloud stop procedure¶
# rc-service nginx stop && rc-service php-fpm stop && rc-service redis stop && rc-service postgresql-xx stop
Nextcloud backup procedure¶
Nextcloud backup config:
# rsync -aAXv /var/www/yourhostname.duckdns.org /media/backup/nextcloud-backup/config_`date +"%Y%m%d"`/
PostgreSQL backup database (https://www.postgresql.org/docs/xx/backup.html):
Nextcloud data backup:
# rsync -aAXv /media/raid/nextcloud-data /media/backup/nextcloud-backup/data_`date +"%Y%m%d"`/
# rsync -aAXv /media/raid/nextcloud-media /media/backup/nextcloud-backup/media_`date +"%Y%m%d"`/
Nextcloud restore procedure¶
TODO
Nextcloud change data directory procedure¶
$ sudo -u nginx php /var/www/yourhostname.duckdns.org/htdocs/nextcloud/occ maintenance:mode --on
$ sudo cp -r /path-to-old-directory/nextcloud-data /path-to-new-directory/nextcloud-data
$ sudo vi /var/www/yourhostname.duckdns.org/htdocs/nextcloud/config/config.php
> 'datadirectory' => '/path-to-new-directory/nextcloud-data',
$ sudo chown -R nginx /path-to-new-directory/nextcloud-data
$ sudo -u nginx php /var/www/yourhostname.duckdns.org/htdocs/nextcloud/occ files:scan --all
$ sudo -u nginx php /var/www/yourhostname.duckdns.org/htdocs/nextcloud/occ maintenance:mode --off
Nextcloud direct files copy procedure¶
$ sudo cp -r /path-to-files/files-folder /path-to-data/nextcloud-data/user/files/files-folder
$ sudo chown -R nginx /path-to-data/nextcloud-data
$ sudo -u nginx php /var/www/yourhostname.duckdns.org/htdocs/nextcloud/occ files:scan --all
Nextcloud restart procedure¶
# nginx -t && rc-service nginx stop && rc-service php-fpm restart && rc-service redis restart && rc-service postgresql-xx restart && redis-cli -s /run/redis/redis.sock
> FLUSHALL
> quit
# rc-service nginx start
Nextcloud restore advanced SSL certs config¶
If your server was down for too long, your "auto renew certificates" script (run Cron job) may fail. In this case you will have to manually restore them:
# vi /etc/nginx/conf.d/nextcloud.conf # add acm-challenge location and turn off https
> ...
~ > # server {
~ > # listen 80;
~ > # listen [::]:80;
~ > # server_name yourhostname.duckdns.org;
~ > #
~ > # # enforce https
~ > # return 301 https://$server_name:443$request_uri;
~ > # }
>
> server {
~ > # listen 443 ssl http2;
~ > # listen [::]:443 ssl http2;
+ >
+ > listen 80;
+ > listen [::]:80;
+ > server_name yourhostname.duckdns.org;
+ >
+ > location ^~ /.well-known/acme-challenge/ {
+ > alias /var/www/yourhostname.duckdns.org/acme-challenge/;
+ > try_files $uri =404;
+ > }
>
> # Use Mozilla's guidelines for SSL/TLS settings
> # https://mozilla.github.io/server-side-tls/ssl-config-generator/
> # NOTE: some settings below might be redundant
>
~ > ssl_certificate /etc/ssl/nextcloud/yourhostname.crt;
~ > ssl_certificate_key /etc/ssl/nextcloud/yourhostname.key;
>
~ > # ssl_certificate /var/lib/letsencrypt/signed_chain.crt;
~ > # ssl_certificate_key /var/lib/letsencrypt/domain.key;
>
~ > # ssl_session_timeout 1d;
~ > # ssl_session_cache shared:MozSSL:10m;
~ > # ssl_session_tickets off;
>
~ > # ssl_dhparam /var/lib/letsencrypt/dhparam4096.pem;
~ >
~ > # ssl_protocols TLSv1.2 TLSv1.3;
~ > # ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
~ > # ssl_prefer_server_ciphers on;
> ...
~ > # add_header Strict-Transport-Security "max-age=15768000; includeSubDomains" always;
> ...
~ > # add_header Strict-Transport-Security "max-age=15768000; includeSubDomains" always;
> ...
# rc-service nginx restart
$ sudo -i
# acme-tiny --account-key /var/lib/letsencrypt/account.key --csr /var/lib/letsencrypt/domain.csr --acme-dir /var/www/yourhostname.duckdns.org/acme-challenge/ > /var/lib/letsencrypt/signed_chain.crt
# exit
# cp /var/lib/letsencrypt/signed_chain.crt /var/lib/letsencrypt/signed_chain.crt.back # backup signed_chain.crt just in case
# vi /etc/nginx/conf.d/nextcloud.conf # turn https back on and ssl certs
> ...
> server {
> listen 80;
> listen [::]:80;
> server_name yourhostname.duckdns.org;
>
> location ^~ /.well-known/acme-challenge/ {
> alias /var/www/yourhostname.duckdns.org/acme-challenge/;
> try_files $uri =404;
> }
>
> # enforce https
> return 301 https://$server_name:443$request_uri;
> }
>
> server {
> listen 443 ssl http2;
> listen [::]:443 ssl http2;
>
> # Use Mozilla's guidelines for SSL/TLS settings
> # https://mozilla.github.io/server-side-tls/ssl-config-generator/
> # NOTE: some settings below might be redundant
>
> #ssl_certificate /etc/ssl/nextcloud/yourhostname.crt;
> #ssl_certificate_key /etc/ssl/nextcloud/yourhostname.key;
>
> ssl_certificate /var/lib/letsencrypt/signed_chain.crt;
> ssl_certificate_key /var/lib/letsencrypt/domain.key;
>
> ssl_session_timeout 1d;
> ssl_session_cache shared:MozSSL:10m;
> ssl_session_tickets off;
>
> ssl_dhparam /var/lib/letsencrypt/dhparam4096.pem;
>
> ssl_protocols TLSv1.2 TLSv1.3;
> ssl_ciphers ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA;
> ssl_prefer_server_cipher on;
>
> ...
>
> add_header Strict-Transport-Security "max-age=15768000; includeSubDomains" always;
>
> ...
>
> add_header Strict-Transport-Security "max-age=15768000; includeSubDomains" always;
> ...
# rc-service nginx restart
Nextcloud update procedure¶
-
! Stop Nextcloud (see Nextcloud stop procedure) and backup everything (see Nextcloud backup procedure) !
-
! Update your "Nextcloud packages" (Nextcloud, Nginx, Redis,
php-fpm
and PostgreSQL) on by one
DO NOT UPDATE THEM ALL AT THE SAME TIME !
/var/www/yourhostname.duckdns.org/htdocs/nextcloud/config/config.php
might have to be changed back after a Nextcloud update
Nextcloud package¶
# emerge -uD nextcloud
# webapp-config --upgrade nextcloud 42.0.2 --host yourhostname.duckdns.org # e.g. update to 42.0.0
PHP package¶
See PHP.
After the update you might have to reproduce ?every? PHP related steps of this guide.
Redis package¶
See Redis.
After the update you might have to reproduce ?every? Redis related steps of this guide.
Nginx package¶
See Nginx.
After the update you might have to reproduce ?every? Nginx related steps of this guide.
PostgreSQL package¶
See PostgreSQL.
After the update you might have to reproduce ?every? PostgreSQL related steps of this guide.
Restart¶
After properly updating one of those packages, don't forget to update the
/var/lib/portage/world
file accordingly if needed.
Finally, restart Nextcloud (see Nextcloud restart procedure).
Troubleshooting¶
-
check services (make sure they are running, not stopped nor crashed):
- if one of those is not working correctly, try to run it manually and see what happens, e.g with Redis:
-
check the logs :
/var/log/nextcloud.log
/var/log/nginx/
/var/log/redis/
/var/log/php-fpm.log
- PostgreSQL logs (see https://www.endpoint.com/blog/2014/11/12/dear-postgresql-where-are-my-logs TODO?)
-
check that the
occ
command is working well (if it doesn't, look at what it shoot):
Secure connection failed and Firefox did not connect¶
If you get this error, this is most likely because your certificate expired...
- this might also because of HSTS history (
Strict-Transport-Security
header with pre loading opt)?
Server not accessible inside local network (but accessible from outside)¶
- This might be because there is no NAT loop back configured on your router (see https://en.wikipedia.org/wiki/Hairpinning).
Curl error 28 - app store blank - no apps shown - request timeout¶
> Change line 404 in 3rdparty/guzzlehttp/guzzle/src/Handler/CurlFactory.php
> increase 1000 to 10000
> In lib/private/App/AppStore/Fetcher/Fetcher.php
> On line 98 change the timeout from 10 to 30 or 90
> in lib/private/Http/Client.php [now lib/private/Http/Client.php]
> On line 66 change the timeout from 30 to 90 [now line 71]
> These changes migh work for you if your connection is slow. They will also invalidate the code
> checks so Nextcloud will complain on the update page.
> They will also disapear when you upgrade Nextcloud to a new version.
TODO¶
- Check security and setup warnings from https://yourhostname.duckdns.org/settings/admin/overview
- Check emails alerts (from nut and
smartmontools
). - Create a script that converts the Bitwarden JSON export into a good CSV
- Compare streaming performance with https://github.com/jellyfin/jellyfin/
- Kodi for streaming ? (https://ownyourbits.com/2018/09/16/stream-media-files-from-nextcloud-to-your-android-and-ios-device-with-kodi/)
If this cheat sheet has been useful to you, then please consider leaving a star here.