Startseite Cloud im Eigenbau – Webserver
Eintrag
Abbrechen

Cloud im Eigenbau – Webserver

Im Beispiel werden zwei Webserver eingerichtet. Die Systeme arbeiten als active/passive Cluster. Als Webserver kommt Apache mit PHP zum Einsatz, installiert unter Oracle Linux 8.6. Die Daten werden über DRBD synchron gehalten, die Dienste werden über Pacemaker gesteuert.

Folgende Topologie wird eingerichtet:

Netzwerkplan

Festplatten einbinden

Die Userdaten liegen auf einer DRBD Partition. Es wird das Verzeichnis /cloudstore erstellt. 

Das Device /dev/sda wird per LVM vorbereitet und der Volumegruppe ol hinzugefügt.

1
2
3
4
5
6
fdisk /dev/sda
n p 1 <enter> <enter> t 8e w
pvcreate /dev/sda1
vgextend ol /dev/sda1
lvcreate -n cloud -l +100%FREE ol
mkdir /cloudstore

Dies muss auf beiden Nodes ausgeführt werden.

DRBD installieren

Das Oracle 8 Epel Repo muss aktiviert werden.

1
2
dnf install oracle-epel-release-el8
dnf install drbd drbd-bash-completion

DRBD einrichten

Folgende Dateien werden angepasst.

/etc/drbd.d/global_common.conf

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
global {
usage-count no;

}

common {
       handlers {

       }

       startup {
       }

       options {

       }

       disk {
       }

       net {
       }
}

Jetzt wird für den Cloudspeicher das Device /dev/drbd0 eingerichtet.

/etc/drbd.d/cloud.res

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
resource cloud {
        protocol C;
        device /dev/drbd0;
        disk /dev/ol/cloud;
        meta-disk internal;
        handlers {
                split-brain "/usr/lib/drbd/notify-split-brain.sh root";
        }

        net {
        allow-two-primaries;
        cram-hmac-alg sha1;
        shared-secret "xxx";
        }

        syncer {
        rate 100M;
        verify-alg sha1;
        }

        on nc1.decon230.org {
        address 172.23.245.51:7789;
        }

        on nc2.decon230.org {
        address 172.23.245.52:7789;
        }
}

Wichtig: DNS muss funktionieren, sollte dies nicht der Fall sein, muss die /etc/hosts angepasst werden. Die DRBD-Nodes müssen mit der Bezeichnung von uname -a eingetragen werden, andernfalls werden keine DRBD-Devices erstellt.

1
2
3
4
5
drbdadm create-md cloud
initializing activity log
initializing bitmap (320 KB) to all zero
Writing meta data...
New drbd meta data block successfully created.

Dies wird auf beiden Nodes durchgeführt.

Auf der primary & secondary Node wird folgendes ausgeführt:

1
2
systemctl start drbd
drbdadm up cloud

Auf der primary Node 

1
drbdadm primary cloud --force

ausführen.

Jetzt kann mit cat /proc/drbd der Status der Synchronisation geprüft werden.

1
2
3
4
5
6
version: 8.4.11 (api:1/proto:86-101)
srcversion: FC3433D849E3B88C1E7B55C
0: cs:SyncSource ro:Primary/Secondary ds:UpToDate/Inconsistent C r-----
ns:1312392 nr:0 dw:0 dr:1315928 al:8 bm:0 lo:0 pe:1 ua:2 ap:0 ep:1 wo:f oos:9169564
[=>..................] sync ed: 12.6% (8952/10232)M
finish: 0:04:06 speed: 37,168 (37,476) K/sec

Alternativ: watch -n1 'cat /proc/drbd'.

Ein drbdmadm status muss folgendes ausgeben:

1
2
3
4
cloud role:Primary
disk:UpToDate
peer role:Secondary
replication:Established peer-disk:UpToDate

Jetzt kann /dev/drbd0 formatiert werden.

1
2
mkfs -t ext4 /dev/drbd0
mount /dev/drbd0 /cloudstore/

Jetzt können Daten auf das Device kopiert werden. Anschließend wird das Device ausgehangen, drbdadm secondary cloud auf Node 1 ausgeführt, drbdadm primary cloud; mount /dev/drbd0 /cloudstore auf Node 2 ausführen. Die Daten sollten jetzt auf Node 2 zu sehen sein.

Die Schritte werden jetzt für die Inhalte des Webservers wiederholt, für das Device /dev/drbd1. Dieses basiert auf /dev/sdb, welches als LVM www erstellt wird.

/etc/drbd.d/web.res

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
resource web {
        protocol C;
        device /dev/drbd1;
        disk /dev/ol/www;
        meta-disk internal;
        handlers {
                split-brain "/usr/lib/drbd/notify-split-brain.sh root";
        }

        net {
        allow-two-primaries;
        cram-hmac-alg sha1;
        shared-secret "xxx";
        }

        syncer {
        rate 100M;
        verify-alg sha1;
        }

        on nc1.decon230.org {
        address 172.23.245.51:7790;
        }

        on nc2.decon230.org {
        address 172.23.245.52:7790;
        }
}

Cluster konfigurieren

Damit DRBD einen automatischen Failover durchführt, wird Pacemaker als Clustersoftware installiert.

Installation & Aktivierung des Clusters

1
2
3
4
5
6
7
8
9
dnf install pacemaker pcs corosync drbd-pacemaker

systemctl enable --now pcsd.service

usermod -s /bin/bash hacluster

mkdir /home/hacluster

passwd hacluster

Jetzt kann der Cluster initialisiert werden, die Schritte müssen nur auf einem Server ausgeführt werden.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
[root@nc1 ~]# pcs host auth nc1
Username: hacluster
Password:
nc1: Authorized

[root@nc1 ~]# pcs host auth nc2
Username: hacluster
Password:
nc2: Authorized

[root@nc1 ~]# pcs cluster setup cloud nc1 addr=172.23.241.51 nc2 addr=172.23.241.52

Destroying cluster on hosts: 'nc1', 'nc2'...
nc1: Successfully destroyed cluster
nc2: Successfully destroyed cluster
Requesting remove 'pcsd settings' from 'nc1', 'nc2'
nc1: successful removal of the file 'pcsd settings'
nc2: successful removal of the file 'pcsd settings'
Sending 'corosync authkey', 'pacemaker authkey' to 'nc1', 'nc2'
nc1: successful distribution of the file 'corosync authkey'
nc1: successful distribution of the file 'pacemaker authkey'
nc2: successful distribution of the file 'corosync authkey'
nc2: successful distribution of the file 'pacemaker authkey'
Sending 'corosync.conf' to 'nc1', 'nc2'
nc1: successful distribution of the file 'corosync.conf'
nc2: successful distribution of the file 'corosync.conf'
Cluster has been successfully set up.

[root@nc1 ~]# pcs cluster start --all
nc1: Starting Cluster...
nc2: Starting Cluster...

[root@nc1 ~]# pcs cluster enable --all
nc1: Cluster Enabled
nc2: Cluster Enabled

pcs property set stonith-enabled=false
pcs property set no-quorum-policy=ignore

Damit ist der Clusterdienst eingerichtet.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
[root@nc1 ~]# pcs status
Cluster name: cloud
Cluster Summary:
* Stack: corosync
* Current DC: nc2 (version 2.1.2-4.0.1.el8_6.2-ada5c3b36e2) - partition with quorum
* Last updated: Wed Jul 13 12:08:29 2022
* Last change: Wed Jul 13 12:06:55 2022 by root via cibadmin on nc1
* 2 nodes configured
* 0 resource instances configured

Node List:
* Online: [ nc1 nc2 ]

Full List of Resources:
* No resources

Daemon Status:
corosync: active/enabled
pacemaker: active/enabled
pcsd: active/enabled

Services einrichten

virtuelle IP

Die Services werden über die IP 172.23.241.50 erreichbar gemacht.

1
2
3
4
5
[root@nc1 ~]# pcs resource create VIP ocf:heartbeat:IPaddr2 ip=172.23.241.50 \
 cidr_netmask=24 op monitor interval=30s

[root@nc1 ~]# pcs resource
* VIP (ocf::heartbeat:IPaddr2): Started nc1

DRBD

Beim Dateisystem müssen Abhängigkeiten und Startreihenfolgen beachtet werden. Da diese Konfiguration komplex ist, wird sie im ersten Schritt in eine Konfigurationsdatei geschrieben, anschließend in den Cluster geladen.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
[root@nc1 ~]# pcs cluster cib cluster.cfg

pcs -f cluster.cfg resource create clouddata ocf:linbit:drbd drbd_resource=cloud \
op monitor interval=30s

pcs -f cluster.cfg resource promotable clouddata clone_clouddata master-max=1 \
 master-node-max=1 clone-max=2 clone-node-max=1 notify=true

pcs -f cluster.cfg resource create fs_clouddata ocf:heartbeat:Filesystem \
device="/dev/drbd0" directory="/cloudstore" fstype="ext4"

pcs -f cluster.cfg constraint colocation add clone_clouddata with VIP INFINITY

pcs -f cluster.cfg constraint order VIP then clone_clouddata

pcs -f cluster.cfg constraint colocation add fs_clouddata with \
clone_clouddata INFINITY

pcs -f cluster.cfg constraint order promote clone_clouddata \
then start fs_clouddata

[root@nc1 ~]# pcs -f cluster.cfg resource status
* VIP (ocf::heartbeat:IPaddr2): Started nc1
* Clone Set: clone_clouddata [clouddata] (promotable):
* Stopped: [ nc1 nc2 ]
* fs_clouddata (ocf::heartbeat:Filesystem): Stopped

[root@nc1 ~]# pcs cluster cib-push cluster.cfg
CIB updated

Jetzt sollte die Partition /cloudstore gemountet sein.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
[root@nc1 ~]# mount | grep -i cloud
/dev/drbd0 on /cloudstore type ext4 (rw,relatime)

[root@nc1 ~]# pcs status
Cluster name: cloud
Cluster Summary:
* Stack: corosync
* Current DC: nc1 (version 2.1.2-4.0.1.el8_6.2-ada5c3b36e2) - partition with quorum
* Last updated: Wed Jul 13 13:44:37 2022
* Last change: Wed Jul 13 13:32:35 2022 by root via cibadmin on nc1
* 2 nodes configured
* 4 resource instances configured

Node List:
* Online: [ nc1 nc2 ]

Full List of Resources:
* VIP (ocf::heartbeat:IPaddr2): Started nc1
* Clone Set: clone_clouddata [clouddata] (promotable):
* Masters: [ nc1 ]
* Stopped: [ nc2 ]
* fs_clouddata (ocf::heartbeat:Filesystem): Started nc1

Daemon Status:
corosync: active/enabled
pacemaker: active/enabled
pcsd: active/enabled

Jetzt muss die Partition für den Webserver eingerichtet werden.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
pcs cluster cib apache.cfg

pcs -f apache.cfg resource create webdata ocf:linbit:drbd drbd_resource=web op monitor interval=30s

pcs -f apache.cfg resource promotable webdata clone_webdata master-ax=1 master-node-max=1 clone-max=2 clone-node-max=1 notify=true

pcs -f apache.cfg resource create fs_webdata ocf:heartbeat:Filesystem device="/dev/drbd1" directory="/var/www" fstype="ext4"

pcs -f apache.cfg constraint colocation add clone_webdata with VIP INFINITY

pcs -f apache.cfg constraint order VIP then clone_webdata

pcs -f apache.cfg constraint colocation add fs_webdata with clone_webdata INFINITY

pcs -f apache.cfg constraint order promote clone_webdata then start fs_webdata

pcs -f apache.cfg resource status

pcs cluster cib-push apache.cfg

Damit ist die Partition /var/www gemountet und einsatzbereit.

1
2
[root@nc1 ~]# mount | grep -i www
/dev/drbd1 on /var/www type ext4 (rw,relatime)

Apache 

Für den Webserver muss ebenfalls eine Ressource erstellt werden, vorher muss dieser jedoch erstmal installiert werden.

1
2
3
4
5
dnf install oracle-epel-release-el8 -y
dnf install httpd mod_qos mod_ssl -y
cd /var/www
chown apache:apache /html
chmod 750 /html

Sollte mod_reqtime beim Apache in Verwendung sein, muss dieses Modul deaktiviert werden, andernfalls kommt es zu php_fcgid Fehlern.

1
2
3
4
5
vi /etc/httpd/conf.d/status.conf
<Location /server-status>
    SetHandler server-status
    Require local
</Location>

Jetzt muss die Clusterressource erstellt werden.

1
2
3
4
5
6
7
8
9
10
11
pcs cluster cib httpd.cfg

pcs -f httpd.cfg resource create httpd ocf:heartbeat:apache configfile=/etc/httpd/conf/httpd.conf statusurl=http://127.0.0.1/server-status

pcs -f httpd.cfg constraint colocation add httpd with VIP INFINITY

pcs -f httpd.cfg constraint order fs_webdata then start httpd

pcs -f httpd.cfg constraint order VIP then httpd

pcs cluster cib-push httpd.cfg

Anschließend sollte Apache starten.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
[root@nc1 ~]# pcs status
Cluster name: cloud
Cluster Summary:
* Stack: corosync
* Current DC: nc1 (version 2.1.2-4.0.1.el8_6.2-ada5c3b36e2) - partition with quorum
* Last updated: Wed Jul 13 14:51:47 2022
* Last change: Wed Jul 13 14:50:47 2022 by root via cibadmin on nc1
* 2 nodes configured
* 8 resource instances configured

Node List:
* Online: [ nc1 nc2 ]

Full List of Resources:
* VIP (ocf::heartbeat:IPaddr2): Started nc1
* Clone Set: clone_clouddata [clouddata] (promotable):
* Masters: [ nc1 ]
* Stopped: [ nc2 ]
* fs_clouddata (ocf::heartbeat:Filesystem): Started nc1
* Clone Set: clone_webdata [webdata] (promotable):
* Masters: [ nc1 ]
* Stopped: [ nc2 ]
* fs_webdata (ocf::heartbeat:Filesystem): Started nc1
* httpd (ocf::heartbeat:apache): Started nc1

Daemon Status:
corosync: active/enabled
pacemaker: active/enabled
pcsd: active/enabled

Der Webserverprozess wird somit erst aktiviert, nachdem DRBD /dev/drbd1 nach /var/www gemountet hat. Diese Reihenfolge ist wichtig, anderfalls wird Apache nicht starten. 

Durch Pacemaker kann apachectl nicht mehr verwendet werden, daher muss der Prozess mit pcs resource restart httpd gesteuert werden.

PHP

Als Skriptsprache wird PHP 8.0.x verwendet. PHP wird folgendermaßen installiert:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
dnf install https://rpms.remirepo.net/enterprise/remi-release-8.rpm
dnf module reset php -y
dnf module enable php:remi-8.0

dnf install -y php php-cli php-common php-pdo php-fpm php-mbstring php-opcache php-sodium php-xml \
php-mbstring php-intl php-pecl-zip php-pecl-apcu php-gmp php-bcmath php-ldap php-pecl-xmlrpc \
php-process php-soap php-tidy php-pecl-imagick php-mysqlnd php-pear php-fedora-autoloader \
php-pecl-redis5 php-pecl-igbinary php-pecl-msgpack php-pecl-mcrypt php-gd
/etc/php.ini anpassen:
output_buffering = Off
max_execution_time = 300
max_input_time = 300
memory_limit = 4096M
post_max_size = 1024M
upload_max_filesize = 1024M
max_file_uploads = 100
file_uploads = On

Jetzt kann mittels systemctl restart php-fpm der Prozess gestartet werden, der Webserver sollte jetzt PHP-Skripte ausführen. PHP-FPM wird ebenfalls über Pacemaker gesteuert und nach dem Webserverprozess gestartet.

1
2
3
4
5
6
7
8
9
10
11
pcs cluster cib phpfpm.cfg

pcs -f phpfpm.cfg resource create phpfpm systemd:php-fpm

pcs -f phpfpm.cfg constraint colocation add phpfpm with VIP INFINITY

pcs -f phpfpm.cfg constraint order httpd then start phpfpm

pcs -f phpfpm.cfg constraint order VIP then phpfpm

pcs cluster cib-push phpfpm.cfg

Der Clusterstatus sollte jetzt so aussehen:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
[root@nc1 ~]# pcs status
Cluster name: cloud
Cluster Summary:
* Stack: corosync
* Current DC: nc1 (version 2.1.2-4.0.1.el8_6.2-ada5c3b36e2) - partition with quorum
* Last updated: Fri Jul 15 17:28:39 2022
* Last change: Fri Jul 15 12:18:49 2022 by root via cibadmin on nc1
* 2 nodes configured
* 9 resource instances configured

Node List:
* Online: [ nc1 nc2 ]

Full List of Resources:
* VIP (ocf::heartbeat:IPaddr2): Started nc1
* Clone Set: clone_clouddata [clouddata] (promotable):
* Masters: [ nc1 ]
* Stopped: [ nc2 ]
* fs_clouddata (ocf::heartbeat:Filesystem): Started nc1
* Clone Set: clone_webdata [webdata] (promotable):
* Masters: [ nc1 ]
* Stopped: [ nc2 ]
* fs_webdata (ocf::heartbeat:Filesystem): Started nc1
* httpd (ocf::heartbeat:apache): Started nc1
* phpfpm (systemd:php-fpm): Started nc1

Daemon Status:
corosync: active/enabled
pacemaker: active/enabled
pcsd: active/enabled

Somit sind Dateisystem, Webserver und Cluster installiert und (grob) konfiguriert.

Nextcloud installieren

Nextcloud herunterladen, entpacken und in die Webserverroot kopieren.

1
2
3
4
5
6
7
wget https://download.nextcloud.com/server/releases/latest.zip
unzip latest.zip
cp -rv nextcloud/* /var/www/html
cd /var/www/html
chown -R apache:apache *
find . -type f -print0 | xargs -0 chmod 640
find . -type d -print0 | xargs -0 chmod 750

Das setzen der Rechte sollte, im Gegensatz zu GFS, schnell erledigt sein.

Anschließend wird https://172.23.241.50 aufgerufen (virtuelle IP des Webservercluster) und die Installation gestartet.

Wichtig: bei der Datenbankverbindung wird die virtuelle IP des DB-Loadbalancers eingetragen und Port 3307. Hier ist der HAProxyd gebunden.

Netzwerkplan

Nach der Installation kann sich eingeloggt werden. Es tauchen diverse Fehler im Backend auf. 

Nextcloud konfigurieren

Die config.php muss um alle Webnodes erweitert werden.

1
2
3
4
5
6
7
8
9
'trusted_domains' =>

array (

0 => 'nc1.decon230.org',
1 => 'nc2.decon230.org',
2 => 'nc.decon230.org',

),

Ein lokaler Cache muss angeben werden.

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

Anschließend kann der Fehler 

1
2
3
An unhandled exception has been thrown:
OCP\HintException: [0]: Memcache \OC\Memcache\APCu not available for local cache
(Is the matching PHP module installed and enabled?)

auftreten. Dieser wird mittels vi /etc/php.d/40-apcu.ini und dem aktivieren von apc.enable_cli=1 behoben.

Redis wird als Cache und File Locking Tool eingerichtet. Wer keinen Rediscluster benutzen möchte, verwendet folgende Einstellungen:

1
2
3
4
5
6
7
8
9
10
'filelocking.enabled' => true,
'memcache.locking' => '\OC\Memcache\Redis',
'memcache.distributed' => '\OC\Memcache\Redis',
'redis' => array(
'host' => '172.23.241.60',
'port' => 6379,
'dbindex' => 0,
'password' => 'xxx',
'timeout' => 0.0,
),

Ein Rediscluster wird folgendermaßen konfiguriert:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
'filelocking.enabled' => true,
'memcache.locking' => '\\OC\\Memcache\\Redis',
'memcache.distributed' => '\\OC\\Memcache\\Redis',
'redis.cluster' =>
array (
'seeds' =>
array (
0 => '172.23.241.61:7000',
1 => '172.23.241.62:7000',
2 => '172.23.241.63:7000',
),
'timeout' => '0.0',
'read_timeout' => '0.0',
'password' => 'xxx',
'dbindex' => '0',
'failover_mode' => '\\RedisCluster::FAILOVER_ERROR',
),

Die Datenintegrität wird mittels sudo -u apache php occ maintenance:update:htaccess wiederhergestellt. Anschließend muss im Webinterface auf “Scan” geklickt werden.

Der Fehler Your web server is not properly set up to resolve "/.well-known/nodeinfo". wird  mittels Anpassung im Apachen behoben, ebenfalls der HSTS Fehler.

/etc/httpd/conf.d/nextcloud.conf

1
2
3
4
5
6
Redirect 301 /.well-known/carddav /remote.php/dav
Redirect 301 /.well-known/caldav /remote.php/dav
Redirect 301 /.well-known/webfinger /index.php/.well-known/webfinger
Redirect 301 /.well-known/nodeinfo /index.php/.well-known/nodeinfo

Header always set Strict-Transport-Security "max-age=15552000; includeSubDomains; preload"

Weitere Anpassungen, die nützlich sind:

Telefonregion:

'default_phone_region' => 'DE',

Integritätsprüfung:

'integrity.check.disabled' => true,

Logging:

'loglevel' => 0,

Theme:

'theme' => '',

Apps installieren

Um Collaboration Features zu nutzen, müssen Apps nachinstalliert werden. Entweder geschieht dies über die WebGUI, oder per CLI. Um Deck zu installieren, wird folgender Befehl ausgeführt:

1
2
cd /var/www/html
sudo -u apache php occ app:install deck

Dies kann pro App einzeln ausgeführt werden, oder automatisch per Skript. Apps die sinnvoll sind, sind z. Bsp.

  • announcementcenter
  • bookmarks
  • calendar
  • contacts
  • files_accesscontrol
  • files_automatedtagging
  • files_markdown
  • notes
  • polls
  • quota_warning
  • tasks
  • guests
  • files_rightclick
  • files_mindmap
  • onlyoffice
  • deck
  • drawio
  • checksum
  • extract
  • files_downloadactivity
  • news
  • apporder
  • twofactor_backupcodes
  • twofactor_totp
  • collectives
  • circles
  • groupfolders

Standard Cronjob 

Zwecks Verwaltung wird ein Cronjob benötigt. Dieser kann zwar als Webcron eingerichtet werden, wird jedoch nicht empfohlen. Der Cronjob muss in diesem Falle als Apache laufen.

1
crontab -u apache -e
1
*/15 * * * * /usr/bin/php /var/www/html/cron.php

Damit ist die Cloudsoftware installiert und konfiguriert.

Cluster Cronjob

Da es sich hier um einen aktiv/passive Cluster handelt ist das Dateisystem nur auf dem aktiven Clusternode vorhanden. Als Folge wird ein “normaler” Cronjob auf der passive Node ins Leere verlaufen und Fehlermeldungen bringen. Um dies zu verhindern wird der Cronjob ebenfalls per Pacemaker eingerichtet.

1
2
3
mkdir /opt/cron
vi /opt/cron/nccron
*/15 * * * * apache /bin/php -f /var/www/html/cron.php

Jetzt wird Pacemaker konfiguriert

1
2
3
4
5
6
7
8
9
10
11
12
pcs cluster cib cron.cfg

pcs -f cron.cfg resource create cron-nextcloud ocf:heartbeat:symlink \
link=/etc/cron.d/nccron target=/opt/cron/nccron op monitor interval=30s

pcs -f cron.cfg constraint colocation add cron-nextcloud with VIP INFINITY

pcs -f cron.cfg constraint order httpd then start cron-nextcloud

pcs -f cron.cfg constraint order VIP then cron-nextcloud

pcs cluster cib-push cron.cfg

Damit ist auch der Cronjob hochverfügbar.