Im folgenden habe ich die wichtigsten Tipps und Tricks zusammen getragen, die OwnCloud 9.x auch auf schwacher Hardware zum Rennen bringen. Mein Fokus liegt dabei auf dem Cubietruck bzw. Raspberry PI1/2/3. Die Liste ist selbstverständlich unvollständig – ich freue mich immer über Ergänzungen und Korrekturen in den Kommentaren. OwnCloud 9.x ist noch recht jung und noch nicht lange auf meinem Server. Ich werde die Liste in den nächsten Wochen weiter pflegen und auf neuere OwnCloud-Versionen erweitern. Ich habe dazu meine Anleitung für das Performance-Tuning von OwnCloud 8.x dupliziert und von allen Hinweisen für ältere OwnCloud-Versionen befreit um die Lesbarkeit zu erhöhen. Aktuell sind die Tipps hier auch auf Nextcloud 10 und 11 übertragbar. Ich werde in der nächsten Zeit einen weiteren Artikel zu den Besonderheiten von Nextcloud veröffentlichen, sobald meine Tests mit Nextcloud abgeschlossen sind.

Beginnen wir mit den Standard-Tipps, die man selbstverständlich schon umgesetzt haben sollte. Ich führe sie hier nur kurz als „Merkzettel“ auf.

0. Standard-Tipps

  • Cron verwenden. Damit die Hintergrundaufgaben nicht bei jedem Seitenaufruf ausgeführt werden müssen, ist es extrem empfehlenswert diese via Cronjob ausführen zu lassen:
    # crontab -u www-data -e
    
    */15 * * * * php -f /var/www/owncloud/cron.php 2>&1> /dev/null 
  • Eine zu MySQL kompatible Datenbank verwenden – ich empfehle MariaDB
  • PHP-FPM >7.0.4 mit OpCache und einen Memory-Cache verwenden (siehe unten auch der Hinweis auf APCu)
  • Nginx verwenden

1. OwnCloud-Konfiguration config.php

Die folgenden Einstellungen sollten in der config.php der OwnCloud-Installation vorgenommen werden.

Journal der Activities-App

Falls die Activities-App eingesetzt wird, das Journal nicht endlos anwachsen lassen:

'activity_expire_days' => 90,

Wenn der Cron-Job läuft, wird das Journal der vorgenommenen Aktivitäten auf den angegebenen Zeitraum gekürzt. Bei sehr lange laufenden Installationen kann das Journal recht groß werden und so viel Speicherplatz verschwenden.

Memory-Caching aktivieren

OwnCloud stellt mehrere Backends für das Caching von Daten bereit. Aktuell sind dies:

  • \OC\Memcache\APC Alternative PHP Cache backend
  • \OC\Memcache\APCu APC user backend
  • \OC\Memcache\ArrayCache In-memory array-based backend (nicht empfohlen)
  • \OC\Memcache\Memcached Memcached backend
  • \OC\Memcache\Redis Redis backend
  • \OC\Memcache\XCache XCache backend

Ich bevorzuge und empfehle für OwnCloud wegen der einfachen Installation und Wartung das APCu-Backend. Nicht nur Gentoo, sondern so ziemlich jeden Distribution bringt APCu von Hause aus mit. APCu wird aktiviert via:

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

Memory-Caching Für das File-Locking aktivieren (<PHP7)

In OwnCloud 8.2 wurde die File-Locking-App entfernt und voll auf das so genannte Transactional-File-Locking umgestellt. Standardmäßig verwendet OwnCloud die Datenbank für das Sichern der File-Locks, was je nach Anbindung und Geschwindigkeit der Datenbank zu einem spührbaren Geschwindigkeitsverlust der gesamten OwnCloud-Installation führen kann. Ich empfehle ab OwnCloud 8.2, das Redis-Backend als Memory-Cache zu nutzen. Leider steht pecl-redis für PHP7 noch nicht zur Verfügung. In der config.php sind dafür die folgenden Zeilen einzufügen:

'memcache.local' => '\OC\Memcache\APCu',
'memcache.locking' => '\OC\Memcache\Redis',
'redis' => array(
     'host' => '/var/run/redis/redis.sock',
     'port' => 0,
      ),

Ich empfehle hier aus Gründen der Sicherheit und der Performance auf den Unix-Socket zu setzen und keinen weiteren Port zu exponieren. Meine /etc/redis.conf habe ich weitestgehend unmodifiziert gelassen und nur diese Zeilen eingefügt bzw. verändert:

port 0
unixsocket /var/run/redis/redis.sock
unixsocketperm 770

Die Socket-Datei gehört dabei dem Benutzer „redis“ und der Gruppe „nginx“ (bei mir, kann aber je nach System auch „www“ o.ä. sein). Auf meinem Gentoo-System wird dies in der Datei /etc/conf.d/redis konfiguriert:

# Redis user.
REDIS_USER="redis"
# Redis group.
REDIS_GROUP="nginx"

2. allgemeine Systemoptimierungen

Bei DynDNS-Domainnamen externen Hostnamen in Hosts-Datei eintragen

Für den Zugriff auf die OwnCloud über den (externen) Namen der Webseite, der z.B. bei DynDNS-Domains, wird sehr viel Zeit verbraucht, weil für die Namensauflösung der DNS des Gateways und über diesen der DNS des DynDNS-Anbieters verwendet wird. Wenn der externe Name in die /etc/hosts-Datei eingetragen wird, fällt die komplette Namensauflösung weg.

TMP-FS

Um das Erstellen und Verwalten von Session in OwnCloud zu beschleunigen, sollte das TMP-Dateisystem auf einem schnellen Medium wie einer SSD oder gar auf einer RAM-Disk liegen, was via /etc/fstab so erreicht werden kann:

tmpfs /tmp tmpfs defaults,noatime,nosuid,nodev,noexec,mode=1777 0 0

XDG-Cache-Verzeichnis in die RAM-Disk legen

Viele von der OwnCloud verwendeten Tools wie z.B. Imagemagick nutzen die Environment-Variable XDG_CACHE_HOME um ihre Caches abzulegen. Damit diese nicht auf einem (potentiell) langsamen Speichermedium erstellt werden müssen, sollte man dies in die RAM-Disk legen:

export XDG_CACHE_HOME="/dev/shm/.cache"

Einen modernen Kernel (ab Kernel 4.x) verwenden

Moderne Kernels – gerade für den Cubietruck – bieten zahlreiche Performance-Optimierungen am Netzwerk-Stack, an den Dateisystemen und bei der Lastverteilung auf die CPUs. Auf meiner Kernel-Seite für den Cubietruck stelle ich die jeweils aktuellen Kernels als binäres Image zur Verfügung – sie sind als Drop-In-Replacement für den leider noch zu oft verwendeten Android-Kernel 3.4 gedacht. Die Linux-Kernels ab 4.8 haben hier insbesondere zugelegt. Die mittlere Antwortzeit beim Abruf der Kalender-Seite ließ sich nur durch den Tausch des Kernels um etwa 10% verbessern.

Ein modernes/performantes Dateisystem verwenden

Wenn auf dem System ein hinreichend aktueller Kernel läuft (also ein >4.x Kernel), lohnt es sich die OwnCloud-Dateien und die Datenbank auf einem BTRFS formatierten Datenträger abzulegen. In meinem System liegt die OwnCloud auf einer WD-Red 2.5″ Festplatte am SATA-Port des Cubietrucks. Der Wechsel auf BRTFS verkürzte die Antwortzeit (ohne Caching) um etwa 30%. Für den Cubietruck sollte auf jeden Fall ein Mainline-Kernel genutzt werden, denn in den von den Android-Builds portierten 3.4.x Kernels ist BTRFS noch nicht hinreichend stabil und performant. Meine Kernel-Builds für den Cubietruck stelle ich auf dieser Seite zur Verfügung.
Wer seine Cloud von einem Flash-Speicher aus betreibt sollte einmal einen Blick auf F2FS werfen. Dieses geht mit den oft eher langsamen sequentiellen Leseraten von SD-Karten besser um und schont die CPU bei Zugriffen. Wer auf eine SSD am SATA-Anschluss zurückgreifen kann, braucht sich über das Dateisystem nur wenig Gedanken zu machen und liegt mit BTRFS oder EXT4 auf der sicheren Seite.

Ein wichtiger Aspekt ist bei EXT4 noch anpassungswürdig. Das Schreiben des Zeitstempels für lesende Zugriffe auf die Datei sollte auf Servern mit Magnetfestplatte oder SD-Karte deaktiviert werden. Dazu wird in die Mount-Parameter die Option „noatime“ aufgenommen. Exemplarisch sieht das in der /etc/fstab so aus:


/dev/sda2  /  ext4  noatime  0 1

Latenzoptimierung des Ondemand-Schedulers

Der Ondemand-Scheduler des Kernels ist für die Regelung der Taktfrequenzen des Hauptprozessors zuständig. Gerade auf dem Cubietruck ist dieser jedoch für hohe Latenzen beim Laden von Webseiten verantwortlich, weil er zu spät den Takt erhöht. Bei den 3.4er-Kernels steht der wesentlich besser funktionierende „interactive“-Scheduler zur Verfügung, bei den Mainline-Kernels jedoch nicht. Die Performance lässt sich hier durch eine geeignete Parametrisierung des ondemand-Schedulers verbessern. Ich lade die Einstellungen über die (anzulegende) Datei /etc/local.d/ondemand_tuning.start:

#!/bin/sh
echo ondemand > /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor
echo 1008000 > /sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq
echo 408000 > /sys/devices/system/cpu/cpu0/cpufreq/scaling_min_freq
echo 25 > /sys/devices/system/cpu/cpufreq/ondemand/up_threshold
echo 10 > /sys/devices/system/cpu/cpufreq/ondemand/sampling_down_factor
echo 1 > /sys/devices/system/cpu/cpufreq/ondemand/io_is_busy

Wichtig hier ist insbesondere auch die Limitierung der minimalen Taktfrequenz auf 408MHz – wird eine geringere Frequenz gewählt, dauert das Aufwachen bzw. der Wechsel in den Idle-Zustand deutlich länger.

weitere Latenzoptimierungen

Auch die Art und Weise wie der Kernel neu erstellte Prozesse auf die Kerne verteilt, hat einen großen Einfluss auf die Responsivität des Servers. Eine auf Desktop-Systemen sehr nützliche Einstellung ist die Auto-Gruppierung des Scheduler. Hier werden normalerweise Prozesse je nach TTY gruppiert um die gefühlte Performance auf einem interaktiven System zu verbessern. Allerdings verhindert dies auch die Migration von erzeugten Kind-Prozessen auf andere CPUs, was auf einem Server mit einem sehr, sehr lange laufenden Daemon kontraproduktiv ist. Autogrouping wird in der /etc/sysctl.conf deaktiviert:

kernel.sched_autogroup_enabled = 0

PHP den Zugriff auf /dev/urandom gestatten

Während /dev/random bei unzureichender Menge von Zufallszahlen blockiert, liefert /dev/urandom immer eine Antwort – auch wenn diese evtl. aus Pseudo-Zufallszahlen besteht, was aber gerade im Umfeld der OwnCloud keinen große Rolle spielen sollte. Man sollte hier sowohl die Zugriffsrechte überprüfen, als auch ob der Zugriff evtl. durch ein konfiguriertes „open_basedir“ in der php.ini evtl. unmöglich ist.

Netzwerk-Optimierungen

Wenn die OwnCloud auf einem System mit leistungsschwacher CPU läuft, sollte man sich überlegen, SYN-Cookies zu deaktivieren. Diese sind zwar ein gutes Mittel um Denial-Of-Service-Attacken abzuwehren, jedoch gilt dies nicht für leistungsschwache Systeme, da hier viel Rechenleistung für die Berechnungen der SYN-Cookies benötigt wird. Ein SYN-Flood-Angriff würde zwar scheitern, jedoch würde dem System dennoch die Puste ausgehen, was den Angriff letztendlich doch gelingen lässt. Die Einstellung ändert man in der Datei /etc/sysctl.conf, die dann für leistungsschwache Systeme so aussieht:

net.ipv4.tcp_syncookies = 0

Auf potenterer Hardware im Sinne der CPU-Leistung sieht dies jedoch genau andersherum aus. Hier sollten SYN-Cookies aktiviert werden und sogar die Anzahl der überwachten Sockets und die Tiefe des Backlogs erhöht werden:

net.ipv4.tcp_syncookies = 1
net.core.somaxconn = 4096
net.ipv4.tcp_max_syn_backlog = 2048

3. Webserver (Nginx)

Alle folgenden Tuning-Tipps beziehen sich auf Nginx und werden in der nginx.conf-Datei vorgenommen. Gerade auf leistungsschwachen Systemen wie den gängigen ARM-Boards (Raspberry-PI, Cubietruck, Banana-PI) ist die Leistung des Crypto-Subsystemes recht schwach – besonders im Vergleich mit modernen Intel-Prozessoren mit AES-NI-Erweiterungen. Eine wichtige Tuningmaßnahme ist daher, die teuren SSL-Session-Setups zu minimieren.

SSL session reuse

Im Nginx sollte auf jeden Fall die Wiederverwertung von SSL Sessions und Session-Tickets aktiviert werden. Dies führt zu einer merklich kürzeren Latenz beim Laden der OwnCloud-Webseiten und erleichtert die „tägliche“ Arbeit mit den jeweiligen OwnCloud-Apps.

ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
ssl_session_ticket_key /etc/ssl/ssl_session_ticket.key;
ssl_session_tickets on;

SPDY-Protokoll bzw. HTTP/2 aktivieren

Nginx ab der Version 1.9.5 im Mainline-Branch unterstützt nun HTTP/2 das als direkter Nachfolger von SPDY gesehen werden kann. Alle wichtigen Browser unterstützen nun auch HTTP/2, daher sollte dieses Protokoll vorgezogen werden. HTTP/2 kann die Zugriffe auf die OwnCloud-Instanz teilweise erheblich beschleunigen.

listen 6443 ssl http2 default deferred;

Steht HTTP/2 nicht zur Verfügung, kann das SPDY-Protokoll verwendet werden. In älteren Versionen (7.x) gab es hier einige Einschränkungen und Fehler, mit OwnCloud 9.x sollten diese nicht mehr auftreten. SPDY wird in der nginx.conf konfiguriert. Hier muss SPDY in die „listen“-Zeile der unterstützten Protokolle aufgenommen werden und die Fähigkeit via Header annonciert werden:

listen 6443 ssl spdy default deferred;

# RSP: add google spdy support -- http://nginx.org/en/docs/http/ngx_http_spdy_module.html#spdy_headers_comp
# http://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_buffer_size
add_header Alternate-Protocol 6443:npn-spdy/3;
spdy_headers_comp 6;
ssl_buffer_size 4k;

Weitere Nginx-Optimierungen

Bei der OwnCloud werden oft viele kleine nacheinanderfolgende Anfragen gestellt – dies gilt besonders für die Kontakte-App. Ein erhöhtes Keepalive/Keepalive-Timeout behält die Sitzung länger offen um nacheinander folgende Anfragen nicht auszubremsen. Die Option „multi_accept“ veranlasst dagegen, den Arbeitsprozess neue Verbindungen anzunehmen bevor die aktuelle Anfrage zu Ende gebracht wird, was sich sehr positiv auf die Latenz auswirken kann.

Im produktiven Einsatz benötigen wir keine Informationen darüber, wann und welche Seiten bzw. Elemente aufgerufen wurden. Damit können wir das Zugriffs-Log deaktivieren und den Druck auf das Dateisystem senken.

Die vorgeschlagenen Änderungen in der nginx.conf sehen so aus:

events {
...
multi_accept on;
...
}

http {
...
keepalive_requests 100000;
keepalive_timeout 75 20;
access_log off;
...}