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:
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
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
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
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
<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
$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
; 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
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
# 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
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.
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
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
# 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
proxy_buffering off;
client_max_body_size 0;
Konfiguration
Vervollständigt ergibt sich folgende Konfiguration
Dockerfile
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
<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
$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
; priority=50
extension=redis
apc.enabled=1
apc.enable_cli=1
opcache.save_comments = 1
opcache.revalidate_freq = 60
opcache.interned_strings_buffer = 64