Nextcloud

From Segfault
Jump to navigation Jump to search

Installation

While Owncloud does provide packages for various distributions[1], Nextcloud only links to 3rd party providers, offering builds of their latest releases.[2]

When installing from the official release:

wget https://download.nextcloud.com/server/releases/nextcloud-20.0.4.tar.bz2{,.sha256,.asc}

gpg --recv-keys 28806A878AE423A28372792ED75899B9A724937A
gpg --verify nextcloud*.bz2.asc
sha256sum -c nextcloud*.tar.bz2.sha256

cd $DOCROOT
tar -xjf nextcloud*.tar.bz2

The webserver needs to be able to write to certain parts of the installation, but not all:

sudo chown -cR root:root nextcloud/
sudo chown -cR www-data:www-data nextcloud/{.htaccess,.user.ini,3rdparty,apps,config,data}

Install some dependencies:[3]

apt install php-fpm php-apcu php-bcmath php-bz2 php-curl php-gd php-gmp php-imagick php-intl php-json php-mbstring php-xml php-zip php-sqlite3 php-mysql php-pgsql php-redis

Enable PHP Opcache:[4]

$ cat /etc/php/7.0/mods-available/opcache.ini
zend_extension=opcache.so
opcache.enable=1
opcache.enable_cli=1
opcache.interned_strings_buffer=8
opcache.max_accelerated_files=10000
opcache.memory_consumption=128
opcache.save_comments=1
opcache.revalidate_freq=1

Prepare the database:

> CREATE USER nextcloud@localhost IDENTIFIED BY 's3cr3t';
> CREATE DATABASE IF NOT EXISTS nextcloud;
> GRANT ALL PRIVILEGES ON nextcloud.* TO nextcloud@localhost;

With all that in place, the installer should start once a web browser is pointed to the document root.

The (newly generated) config/config.php can be adjusted to switch to pretty URLs[5]

 [...]
 'datadirectory' => '/var/www/nextcloud/data',
 'overwrite.cli.url' => 'https://www.example.net/nextcloud',
 'htaccess.RewriteBase' => '/nextcloud',

Re-generate $DOCROOT/.htaccess:

sudo -u www-data php /var/www/nextcloud/occ maintenance:update:htaccess

When serving Nextcloud in a subdirectory, we may also need the following settings on the web server to allow proper service discovery[6]

Redirect 301 /.well-known/carddav /nextcloud/remote.php/dav
Redirect 301 /.well-known/caldav /nextcloud/remote.php/dav

sys_get_temp_dir

It may be necessary to adjust the handling of temporary files. This may even warrant a whole new topic, but let's add this here: the occ command will need to use a temp directory and usually gets the same from PHP:

$ sudo --preserve-env=NEXTCLOUD_CONFIG_DIR -u nextcloud /usr/bin/php -c /etc/php/php.ini -r 'print(sys_get_temp_dir()."\n");'
/var/run/php_tmp

However, since we are running php-fpm, the nextcloud pool does not have write access to that directory:

$ ps -ef | grep pool\ nex[t]
nextclo+    7791    7788  0 22:39 ?        00:00:02 php-fpm: pool nextcloud
nextclo+    7792    7788  0 22:39 ?        00:00:01 php-fpm: pool nextcloud
nextclo+    7820    7788  0 22:39 ?        00:00:01 php-fpm: pool nextcloud

$ ls -ld /var/run/php_tmp
drwxrwx---+ 2 http http 80 Apr  2 22:44 /var/run/php_tmp

We have several options here:

  1. Add nextcloud to the http group, but we may not want to do that, as we will lose some privilege separation.
  2. Add an ExecStartPost rule[7] to php-fpm.service. However, this isn't working out of the box, as current unit files will set ReadWritePaths only to some distinct directories, and we don't want to add another one just yet.
  3. Set an ACL for this directory. This won't work after boot, because PHP may not be running yet, but we can add the same to our occ wrapper script:
/usr/bin/setfacl -m u:nextcloud:rwx /var/run/php_tmp -- that should do the trick.

Caching

According to the documentation, we can use several caching techniques.

APC

php-apcu needs to be installed and enabled:

$ cat /etc/php/conf.d/apcu.ini 
extension=apcu.so
apc.enable_cli=1

So we should have something like this:

$ php -r 'phpinfo();'  | grep apc
apc.enable_cli => On => On
apc.enabled => On => On
[...]

Enable APCu in NextCloud config.php

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

We could also enable the APC statistics page:

$ ln -s /usr/share/webapps/php-apcu/apc.php /var/www/apc.php
$ cat /var/www/apc.conf.php 
<?php
   defaults('ADMIN_USERNAME','admin');
   defaults('ADMIN_PASSWORD','s3cr3t');
?>

Redis

While we could use Memcached for caching, Redis appears[8] to be the better choice. YMMV though.

Install Redis and configure as needed:

$ grep ^[a-z] /etc/redis.conf
bind 127.0.0.1
protected-mode yes
port 0
unixsocket /var/run/redis/redis.sock
unixsocketperm 700
[...]

Make the socket available to the user running the web server:

setfacl -m u:http:rwx /var/run/redis/{,redis.sock}

We will also need the PHP module:

git clone https://github.com/phpredis/phpredis.git phpredis-git
cd phpredis-git
phpize && ./configure && make
sudo install -m0755 -o root -g root modules/redis.so /usr/local/lib/

Enable the module in our PHP config:

$ grep redis /etc/php/conf.d/local.ini 
extension=/usr/local/lib/redis.so

...and in Nextcloud:

$ cat ../nextcloud/config/config.php
[...]
 'memcache.local'       => '\OC\Memcache\APCu',
 'memcache.distributed' => '\OC\Memcache\Redis',
 'memcache.locking'     => '\OC\Memcache\Redis',
 'redis' => [
    'host' => '/var/run/redis/redis.sock',
    'port' => 0,
  ],

TBD:

Previews

With PreviewGenerator installed, showing previews of pictures should be much faster.

occ app:install previewgenerator
occ app:enable previewgenerator
occ preview:generate-all

Install the following as a cronjob (every 10 minutes):

occ preview:pre-generate

Generate only a pre-defined set of preview image sizes:

$ for o in squareSizes widthSizes heightSizes; do occ config:app:set --value="64 256 1024" previewgenerator ${o}; done
Config value squareSizes for app previewgenerator set to 64 256 1024
Config value widthSizes  for app previewgenerator set to 64 256 1024
Config value heightSizes for app previewgenerator set to 64 256 1024

Previews will be generated in a sub directory hierarchy:[9]

 This lovely like is the result of the way the new previews are stored
	* We take the md5 of the name (fileid) and split the first 7 chars. That way

* there are not a gazillion files in the root of the preview appdata.

Let's see:

nextcloud=> \x
Expanded display is on.

nextcloud=> select fileid,name,to_timestamp(storage_mtime)::date from oc_filecache where name like 'PXL%.jpg' order by storage_mtime desc limit 2;
-[ RECORD 1 ]+---------------------------
fileid       | 923652
name         | PXL_20230830_072605631.jpg
to_timestamp | 2023-08-30
-[ RECORD 2 ]+---------------------------
fileid       | 923765
name         | PXL_20230830_173111087.jpg
to_timestamp | 2023-08-30
^D

$ printf 923652 | md5sum | cut -c-7 | sed 's|.|&/|g;s|$|923652|'
4/1/2/d/d/d/d/923652
$ ls -lhgtr /var/lib/nextcloud/data/appdata*/preview/4/1/2/d/d/d/d/923652
total 1.5M
-rw-r--r-- 1 nextcloud 535K Aug 30 09:41 1920-2560-max.jpg
-rw-r--r-- 1 nextcloud  14K Aug 30 09:41 256-256-crop.jpg
-rw-r--r-- 1 nextcloud 1.9K Aug 30 09:45 64-64-crop.jpg
-rw-r--r-- 1 nextcloud 135K Aug 30 09:45 1024-1024-crop.jpg

Databases

sqlite

TBD!

PostgreSQL

TBD!
sudo -u postgres psql
CREATE USER nextcloud WITH PASSWORD 'nextcloud';
CREATE DATABASE nextcloud WITH OWNER nextcloud TEMPLATE template0 ENCODING 'UTF8';
https://pgtune.leopard.in.ua/
vi /etc/postgresql/10/main/postgresql.conf

Update

The built-in updater appears to work just fine. We have to make some preparations first:

DOCROOT=/var/www                                                                          # Adjust as needed!
chown -R www-data:www-data $DOCROOT/nextcloud/

Start the web updater and let it run until:

Keep maintenance mode active?
[x] Maintenance mode will kept active.
Now trigger the migration via command line: ./occ upgrade

And we'll do just that:

sudo -u www-data php $DOCROOT/nextcloud/occ upgrade

If all went well, disable the maintenance mode:

sudo -u www-data php $DOCROOT/nextcloud/occ maintenance:mode --off

Adjust ownerships again:

sudo chown  -R root:root $DOCROOT/nextcloud/
sudo chown -cR www-data:www-data $DOCROOT/nextcloud/{.htaccess,.user.ini,3rdparty,apps,config,data}

Links

References