Nextcloud 25 selber hosten

 | 1268 Wörter


Ahoi,

schon seit Jahren setze ich auf Nextcloud als freie Alternative zu Google Drive, iCloud und OneDrive, doch meine Sammlung von 15 Jahren an Fotos zwang bisher jeden Managed Nextcloud Provider in die Knie. Also bleibt mal wieder nur, es in die eigenen Hände zu nehmen 💪

Da ich Nextcloud genau auf meine Bedürfnisse anpassen wollte, habe ich bei 0 begonnen und nicht das vorgefertigte Docker Image von Nextcloud verwendet. Mal davon abgesehen, dass die Beispielkonfiguration nicht mal stabil ist!

Als Basis habe ich ubuntu/apache2 gewählt:

1
2
3
4
5
FROM ubuntu/apache2:2.4-22.04_beta

ARG DEBIAN_FRONTEND=noninteractive
ENV TZ=Europe/Berlin
RUN apt-get update && apt-get upgrade -y

Dazu teilen wir dem Ubuntu mit, dass wir bitte keine Interaktivität, also Fragen haben wollen und akzeptieren damit die Standardauswahl. Im Anschluss wählen wir unsere Zeitzone, welche aber auch im Nachhinein in der docker-compose.yml ändern können. Dann bereiten wir die Installation von PHP und seinen Erweiterungen vor und ziehen uns Updates.

Für meinen Anwendungsfall benötige ich folgende Packete

1
RUN apt-get install -y libtidy-dev apache2 libapache2-mod-php php-curl php-mbstring php-intl php-gmp php-bcmath php-imagick php-xml php-zip php-gd wget openssl php-common php-curl php-json php-xml php-zip php-dom php-xsl php-pgsql php-apcu php-bz2 php-dompdf php-redis ffmpeg curl php-simplexml php-iconv php-ctype libxml2 php-posix php-fileinfo

wget brauchen wir später, um Nextcloud herunterzuladen und ffmpeg wird von einer Nextcloud Erweiterung für die Thumbnail-Erstellung benötigt.

Nach der Empfehlung aus den Docs erhöhen wir das memory_limit von PHP

1
2
RUN sed -i 's/memory_limit = 128M/memory_limit = 4096M/g' /etc/php/8.1/apache2/php.ini
RUN sed -i 's/memory_limit = 128M/memory_limit = 4096M/g' /etc/php/8.1/cli/php.ini

Und output_buffering muss unbedingt deaktiviert werden

1
RUN sed -i 's/output_buffering = 4096/output_buffering = off/g'  /etc/php/8.1/apache2/php.ini

Damit der apache2 auch weiß, wo er Nextcloud findet und über welche Domain es zu erreichen ist, erstellen wir eine Datei nextcloud.conf

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
<VirtualHost *:80>
  DocumentRoot /var/www/html/
  ServerName  cloud.xtracode.ws

  ErrorLog /dev/stderr
  TransferLog /dev/stdout

  <Directory /var/www/html/>
    Require all granted
    AllowOverride All
    Options FollowSymLinks MultiViews

    <IfModule mod_dav.c>
      Dav off
    </IfModule>
  </Directory>
</VirtualHost>

Diese stammt direkt aus den Docs., mit der Anpassung, dass die Logs an STDOUT gesendet werden. Damit kann man nun auch einen logging driver verwenden oder mit docker-compose logs -f die Logs live verfolgen.

Ebenfalls hat mein Server die Kapazität für Redis und APCu, weswegen ich noch die Standardkonfiguration von Nextcloud erweitern musste. Dazu erstelle die Datei custom.config.php

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
$CONFIG = array (
        'memcache.local' => '\OC\Memcache\APCu',
        'memcache.distributed' => '\OC\Memcache\Redis',
        'redis' => [
             'host' => 'redis',
             'port' => 6379,
        ],
        'memcache.locking' => '\OC\Memcache\Redis',
        'enable_previews' => true,
        'enabledPreviewProviders' =>
        array (
            1 => 'OC\\Preview\\PNG',
            2 => 'OC\\Preview\\JPEG',
            3 => 'OC\\Preview\\GIF',
            4 => 'OC\\Preview\\BMP',
            5 => 'OC\\Preview\\XBitmap',
            6 => 'OC\\Preview\\MP3',
            7 => 'OC\\Preview\\MP4',
            8 => 'OC\\Preview\\TXT',
            9 => 'OC\\Preview\\MarkDown',
            12 => 'OC\\Preview\\Image',
        ),
);

Gerade bei größeren Datenmengen oder sehr vielen Dateien empfiehlt sich Redis fürs File locking einzusetzen. Damit Nextcloud aber auf Redis und APCu (Cache für PHP Laufzeitumgebung), müssen wir diese aktivieren, installiert sind ja beide schon.
custom.ini

1
2
3
4
5
6
7
8
9
; priority=50
extension=redis

apc.enabled=1
apc.enable_cli=1

opcache.save_comments = 1
opcache.revalidate_freq = 60
opcache.interned_strings_buffer = 64

Es sei auf die erste Zeile hinzuweisen. Diese teilt PHP mit, in welcher Reihenfolge die Konfigurationsdateien geladen werden sollen. Ansonsten kann es vorkommen, dass die Redis-Erweiterung vor seiner Abhängigkeit igbinary geladen wird, was zu einem Fehler und der Deaktivierung der Redis-Erweiterung führt.

Nun wollen wir die lokalen Konfigurationsdateien auch in die Dockerumgebung bekommen

1
2
3
COPY ./nextcloud.conf /etc/apache2/sites-available/nextcloud.conf
COPY ./custom.config.php /var/www/html/config/custom.config.php
COPY ./custom.ini /etc/php/8.1/mods-available/custom.ini

Die Konfigurationen müssen nun nur noch aktiviert werden

1
2
3
4
5
6
7
8
# Unsere Konfiguration für die PHP-Umgebung cli aktivieren, benötigt für Cronjobs.
RUN phpenmod -s cli custom
# Analog für apache2
RUN phpenmod -s apache2 custom
# Unsere apache2 Konfiguration aktivieren
RUN a2ensite nextcloud.conf
# Standardkonfiguration deaktivieren
RUN a2dissite 000-default

Nextcloud nutzt außerdem eine ausführliche .htaccess welche einige apache2-Erweiterungen benötigt, welche wir auch noch aktivieren müssen

1
2
3
4
5
RUN a2enmod rewrite
RUN a2enmod headers
RUN a2enmod env
RUN a2enmod dir
RUN a2enmod mime

Final kommen wir nun auch zu der eigentlichen Installation von Nextcloud unter /var/www/html.

1
2
3
4
5
RUN mkdir -pv /var/www/html
WORKDIR /var/www/html
RUN wget https://download.nextcloud.com/server/installer/setup-nextcloud.php -O /var/www/html/setup-nextcloud.php
RUN chown www-data:www-data -R /var/www
RUN runuser -u www-data -- php -v

Damit laden wir den Installer, sichern ihn unter /var/www/html/setup-nextcloud.php und starten zum Schluss einmal PHP, damit könnten wir direkt auf eventuelle Fehler beim Laden unserer Konfiguration reagieren.

Docker Compose

Das ganze lässt sich abschließend in einer docker-compose.yml vereinigen, aber für mich ohne PostgreSQL, Redis oder ElasticSearch. Bei meinen Servern bevorzuge ich geteilte Datenbankserver und Caches zu nutzen und nicht mit jeder docker-compose.yml eine eigenständigen Stack mitzuliefern.
Irgendwann war doch mal Effizienz ein Thema? Aber nun soll man 8 MariaDB Installationen parallel betreiben o_0

docker-compose.yml

 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
version: '3'

services:
  cloud:
    build: .
    restart: unless-stopped
    mem_limit: 4096m
    mem_reservation: 2048M
    cpus: 4.0
    volumes:
      - /mnt/docker/volumes/nextcloud:/var/www/html
      - /mnt/docker/volumes/nextcloud-tmp:/var/tmp
    networks:
      - proxy
      - core_redis
      - core_postgres

networks:
  proxy:
    external:
      true
  core_redis:
    external:
      true
  core_postgres:
    external:
      true

Je nach Konfiguration des Servers kann es nötig sein, das Tmp-Verzeichnis extern zu mappen. Ansonsten könnte es zu Problemen kommen, falls du über WebDav (rclone) riesige Dateien hochlädst, welche die Größe der Tmp-Partition sprengen. Außerdem habe ich drei verschiedene Netzwerke für die Anbindung des Reverse Proxys, PostgreSQL und Redis verknüpft.

Ausführen lässt sich das ganze zum Abschluss so

1
2
3
4
# Docker Image erstellen
docker-compose build
# Docker Container anhand unserer docker-compose.yml erstellen, starten und eventuelle Reste einer vorherigen Installation entfernen
docker-compose up -d --force-recreate --remove-orphans

NGINX Reverse Proxy

Falls du NGINXals Reverse Proxy einsetzt, bitte unbedingt darauf achten, dass folgende Konfiguration enthalten ist oder auf eure Einsatzumgebung angepasst wurde

1
2
proxy_buffering off;
client_max_body_size 0;

Konfiguration

Vervollständigt ergibt sich folgende Konfiguration

Dockerfile

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
FROM ubuntu/apache2:2.4-22.04_beta

ARG DEBIAN_FRONTEND=noninteractive
ENV TZ=Europe/Berlin
RUN apt-get update && apt-get upgrade -y && apt-get install -y libtidy-dev apache2 libapache2-mod-php php-curl php-mbstring php-intl php-gmp php-bcmath php-imagick php-xml php-zip php-gd wget openssl php-common php-curl php-json php-xml php-zip php-dom php-xsl php-pgsql php-apcu php-bz2 php-dompdf php-redis ffmpeg curl php-simplexml php-iconv php-ctype libxml2 php-posix php-fileinfo
RUN sed -i 's/memory_limit = 128M/memory_limit = 4096M/g' /etc/php/8.1/apache2/php.ini
RUN sed -i 's/output_buffering = 4096/output_buffering = off/g'  /etc/php/8.1/apache2/php.ini
COPY ./nextcloud.conf /etc/apache2/sites-available/nextcloud.conf
COPY ./custom.config.php /var/www/html/config/custom.config.php
COPY ./custom.ini /etc/php/8.1/mods-available/custom.ini
RUN phpenmod -s cli custom
RUN phpenmod -s apache2 custom
RUN a2ensite nextcloud.conf
RUN a2dissite 000-default
RUN a2enmod rewrite
RUN a2enmod headers
RUN a2enmod env
RUN a2enmod dir
RUN a2enmod mime
RUN mkdir -pv /var/www/html
WORKDIR /var/www/html
RUN wget https://download.nextcloud.com/server/installer/setup-nextcloud.php -O /var/www/html/setup-nextcloud.php
RUN chown www-data:www-data -R /var/www
RUN runuser -u www-data -- php -v

nextcloud.conf

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
<VirtualHost *:80>
  DocumentRoot /var/www/html/
  ServerName  nextcloud.exmaple.com

  ErrorLog /dev/stderr
  TransferLog /dev/stdout

  <Directory /var/www/html/>
    Require all granted
    AllowOverride All
    Options FollowSymLinks MultiViews

    <IfModule mod_dav.c>
      Dav off
    </IfModule>
  </Directory>
</VirtualHost>

custom.config.php

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
$CONFIG = array (
        'memcache.local' => '\OC\Memcache\APCu',
        'memcache.distributed' => '\OC\Memcache\Redis',
        'redis' => [
             'host' => 'redis',
             'port' => 6379,
        ],
        'memcache.locking' => '\OC\Memcache\Redis',
        'enable_previews' => true,
        'enabledPreviewProviders' =>
        array (
            1 => 'OC\\Preview\\PNG',
            2 => 'OC\\Preview\\JPEG',
            3 => 'OC\\Preview\\GIF',
            4 => 'OC\\Preview\\BMP',
            5 => 'OC\\Preview\\XBitmap',
            6 => 'OC\\Preview\\MP3',
            7 => 'OC\\Preview\\MP4',
            8 => 'OC\\Preview\\TXT',
            9 => 'OC\\Preview\\MarkDown',
            12 => 'OC\\Preview\\Image',
        ),
);

custom.ini

1
2
3
4
5
6
7
8
9
; priority=50
extension=redis

apc.enabled=1
apc.enable_cli=1

opcache.save_comments = 1
opcache.revalidate_freq = 60
opcache.interned_strings_buffer = 64
#apache2 #apcu #cache #docker #ffmpeg #gdrive #google-drive #icloud #mariadb #nextcloud #nginx #onedrive #postgresql #redis #selfhosted #ubuntu #webdav