Nextcloud's high performance backend behind a Sophos reverse proxy

I had the task of setting up a Nextcloud server at a larger company. Since the employees also wanted to work mobile, it was inevitable to implement Nextcloud's high performance backend for files, which has been introduced since version 21.

While it's already relatively difficult to see through what the application does and the documentation is relatively sparse, the marketing name resonated with the company.

To save you a lot of stress, I'll now explain how the whole thing is set up, how to test it, and how I got it to work behind a Sophos reverse proxy, which is barely compatible with web standards anyway.

What is Nextcloud High Performance Backup?

Clients like Nextcloud's Desktop Synch Client or the Android/iOS App poll the server for file changes at regular intervals.
Although this query only takes a few milliseconds, it is performed by every client. With many changes and many clients, this can lead to problems. On the one hand, the realtime nature may be lost, and on the other hand, it is rather inefficient because queries are made even if there are no changes.

Nextcloud's High Performance Backend changes that. Instead of the clients fetching their information from the server, the server notifies the clients via push as soon as there are changes.

This method is not only faster, but also reduces the load on the server because it avoids the constant queries.

This is also useful in practice if you don't have many client connections, because it is simply more efficient.

How to implement it?

Log in to the Nextcloud server.
Install the app via the web GUI "notify_push" or via CLI:

# cd to the Nextcloud installation path
sudo -u www-data php occ app:install notify_push
install notify_push

This app requires a working redis server and for Nextcloud to be configured to use the redis server for file transactions.

Configure the local web server for websockets and restart your server.
The steps differ depending on the webserver used (NGINX, Apache, etc.).

Create a unit file

[Unit]
Description = Push daemon for Nextcloud clients
After=syslog.target network.target \
mariadb.service apache2.service redis.service



[Service]
Environment = PORT=7867
ExecStart=/var/www/nextcloud/apps/notify_push/bin/x86_64/notify_push \
--allow-self-signed \
--nextcloud-url https://<your_public_nextcloud_url> \
/var/www/nextcloud/config/config.php
User=www-data
Restart = always


[Install]
WantedBy = multi-user.target
/etc/systemd/system/notify_push.service

Notify_push needs to start after database and redis. The official documentation unfortunately omits this.

What is unfortunately also not mentioned anywhere, is that the rights in the app must be adjusted.
Go to your Nextcloud installation directory and make the binary executable.

# your Nextcloud app installation path may vary
chmod +x /var/www/nextcloud/apps/notify_push/bin/x86_64/notify_push 
chmod +x notify_push

The 7867 does not need to be opened in the firewall because the ProxyPass directive in the reverse proxy takes care of that.

Sophos reverse proxy

Since the Nextcloud is connected behind a reverse proxy, this must also be configured.
Enter the local IP (not the public IP) of Sophos as a trusted proxy in the Nextcloud config.

 'trusted_proxies' => 
  array (
    0 => 'your_sophos_local_IP',
  ),
config.php

Next, log in to the Sophos XG and create an IP host definition for your Nextcloud under System - Hosts and Services. You enter the local Nextcloud IP as the IP, of course.

Sophos - Hosts and services Nextcloud

After that you can create a WAF rule under Protect / Rules and polices.
Under listening port, enter 443 (you need a TLS certificate) and check HTTPS.  The domain is the public address.
Under Protected servers, check "Path-specific routing".
You need two paths:
For the root ("/") path you can leave everything on default settings.
For the Nextcloud notifiy path "/push/ws" you have to check WebSocket passthrough.
At the bottom you have to check the "Pass host header".

Sophos Nextcloud WAF Firewall rule
Sophos Nextcloud Push Websocket passthrough

In the "NAT" tab you have to create a destination NAT (DNAT) to your local server address, which you have defined under Hosts.

In the "NAT" tab you have to create a destination NAT (DNAT) to your local server address, which you have defined under Hosts.
Set original source to "Any", orginal destination to the public Nextcloud address, translated destination to the local Nextcloud address. The rest can stay at default.

Sophos Nextcloud DNAT

When everything is set up, the System Unit file can be started:

systemctl enable --now notify_push

Please be aware that in 2022, the Sophos XG still does not support http/2 and LetsEncrypt.

Problems and how to test if everything worked?

The app offers the possibility to test the configuration via the CLI.

# cd to the Nextcloud installation path
sudo -u www-data php occ notify_push:self-test

✓ redis is configured
✓ push server is receiving redis messages
✓ push server can load mount info from database
✓ push server can connect to the Nextcloud server
✓ push server is a trusted proxy
✓ push server is running the same version as the app

This self-test was unfortunately deceptive in my case (due to missing websocket passthrough in Sophos at the time).

There is also the possibility to output the metrics of the app.

sudo -u www-data php occ notify_push:metrics
Active connection count: 0
Total connection count: 0
Total database query count: 1
Events received: 3
Messages sent: 0

No matter how many changes I made on Nextcloud, no messages were sent.
The number of active connection always remained at 0.

The self-test seems to check only limited from the outside. As soon as a client was logged into the intranet, connections were displayed.

This is almost certainly why the High Performance Backend isn't really active on many others, because I've seen this problem on two other instances, independent of the one I implemented.

Fortunately, the developer has thought along. There is a test client through which you can check the connection from the outside. This test is bulletproof.

# test_client <nextcloud url> <username> <password>
[2022-09-22 10:46:38.033202 +02:00] 
INFO [test_client] test_client/src/main.rs:29: 
Found push server at wss://<nextcloud-domanin>/push/ws
[2022-09-22 10:46:38.411428 +02:00] 
INFO [test_client] test_client/src/main.rs:64: Authenticated
notify_push test_client

Things to consider

Even in the case that everything should work, there are problems:

I noticed that the app "notify_push" is not update-proof. I have to do the above command (chmod +x) after every Nextcloud update.

If I take the Sytem Unit setting from the Github page, the app is started before the database and Redis. In this case it stops after a server restart with error.

If you do a sytemctl restart notify_push, everything is green again.