Nextcloud Teil 1: Setup mit Docker & Nginx

Ich bin ja gerne Herr über meine Daten, und das betrifft selbstverständlich auch das Thema Cloud. Daten im internen Netzwerk synchronisere ich nun schon seit längerer Zeit via Syncthing, doch Kontakte, Kalender und Notizen bleiben damit außen vor. Weiteres Problem: Ich kann nicht unterwegs auf Daten zugreifen die noch auf dem Server liegen, denn Syncthing synchronisiert entweder ganz oder gar nicht, später herunterladen ist nicht.

Weiteres Problem: Ich habe keine großartige Lust erst dutzende Pakete zu installieren um dann noch endlos diese zu konfigurieren bis meine private Cloud einsatzbereit ist. Ich will das herunterladen, starten, und dann muss das laufen.

Wie nun die Lösung des ganzen lautet? Nextcloud! Und zwar schön verpackt als Docker Container. Wie das ganze installiert und konfiguriert wird (denn ganz ohne geht es dann doch nicht) zeige ich im folgenden Artikel.

Achtung!
Dieser Artikel behandelt neben dem Hintergrundwissen lediglich die Installation von Nextcloud mittels Docker ohne einen separaten Datenbankserver zu nutzen. Wer mehr Performance braucht sollte diesem Artikel folgen. Hier wird zusätzlich die Installation eines PostgreSQL Datenbankservers beschrieben.

Docker? Was'n das?

Docker ist eine spezielle Form der Betriebssystemvirtualisierung und erlaubt es mit minimalem Overhead Anwendungen, welche als Container verpackt sind, auf nahezu beliebigen Hosts laufen zu lassen. Über das Docker Hub sind alle möglichen Anwendungen bereits als Container verfügbar, wer also vollständig auf Docker setzen möchte kann ein minimales Betriebssystem installieren, und den Rest via Docker erledigen. Webserver, Anwendungen, virtualisiert, schön verpackt, portabel, leicht zu verwalten und vor allem: Ohne großartigen Aufwand.

Docker installieren

Auf meinem Server setze ich zur Zeit Ubuntu 16.04 LTS ein, und wer mag kann auch das in den Ubuntu Repositories verfügbare docker.io-Paket installieren, ich hingegen füge wie in der offiziellen Anleitung zu Docker empfohlen eine weitere Paketquelle hinzu.

# apt-get install apt-transport-https ca-certificates curl software-properties-common
# curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
# apt-key fingerprint 0EBFCD88
# add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"

Danach die Paketquellen aktualisieren, das Paket docker installieren und dann kann es auch schon losgehen mit dem eigentlichen Spaß.

# apt-get update
# apt-get install docker

Nextcloud herunterladen, instanziieren & starten

Als nächstes lädt man den Nextcloud Container vom Docker Hub herunter, in welchem die öffentlich verfügbaren Container gelistet werden.

# docker pull nextcloud

Will man eine bestimmte Version herunterladen, lässt sich dies durch Angabe eines Tags erreichen (ohne Angabe wird automatisch das Tag "latest" verwendet):

# docker pull nextcloud:12-apache

Dann legt man noch ein Volume für die Nutzerdaten an, und anschließend kann man in einem Befehl den Container instanziieren und starten:

# docker volume create --name nextcloud-data
# docker run -d -v nextcloud-data:/var/www/html -p 127.0.0.1:32768:80 --name nextcloud-12 nextcloud:12-apache

Die Parameter bewirken dabei folgendes:

  • -d – Den Container im Hintergrund laufen lassen
  • -v nextcloud-data:/var/www/html – Bindet das Volume „nextcloud-data“ im Container unter /var/www/html ein, dort liegen die Nutzerdaten
  • -p 127.0.0.1:32769:80 – Mappt den internen Port 80 auf den lokalen (!) Port 32768 des Hostsystems
  • --name nextcloud-12 – Vergibt den Namen „nextcloud-12“ an den Container
  • nextcloud:12-apache – Gibt den Container an, der als Grundlage dienen soll

Der Container ist somit instanziiert und auch bereits gestartet (Anmerkung: docker run kombiniert die Befehle docker create sowie docker start)

Nginx als Proxy konfigurieren

Damit der Container auch extern erreichbar ist muss der auf dem Host laufende Nginx Webserver noch als Proxy konfiguriert werden (die Installation und weitere Konfiguration lasse ich hier außen vor – darüber gibt es im Internet bereits ausreichend Artikel zu finden). Der „server“-Abschnitt der nginx.conf muss dabei etwa wie folgt erweitert werden:

server {
    listen      443 ssl http2; # IPv4, SSL/TLS, HTTP/2
    listen [::]:443 ssl http2; # IPv6, SSL/TLS, HTTP/2
    server_name example.org;
    root /var/www/nextcloud;
    index index.html;
    # Let's Encrypt on port 443
    location ^~ /.well-known {
        root /var/www/letsencrypt;
    }

    # Raise file upload size
    client_max_body_size 512m;

    # Limit download size
    proxy_max_temp_file_size 4096m;

    # Proxy for nextcloud docker
    location / {
        # Headers are already set via https://github.com/nextcloud/server under lib/private/legacy/response.php#L242 (addSecurityHeaders()) 
        # We only need to set headers that aren't already set via nextcloud's addSecurityHeaders()-function 
        add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload";
        add_header Referrer-Policy "same-origin";

        # Secure Cookie / Allow cookies only over https
        # https://en.wikipedia.org/wiki/Secure_cookies
        # https://maximilian-boehm.com/hp2134/NGINX-as-Proxy-Rewrite-Set-Cookie-to-Secure-and-HttpOnly.htm
        proxy_cookie_path / "/; secure; HttpOnly";

        # And don't forget to include our proxy parameters
        #include /etc/nginx/proxy_params;
        proxy_set_header Host $http_host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;

        # Connect to local port
        proxy_pass http://127.0.0.1:32768; # Don't use http://localhost:32768
    }
}

Dann noch speichern, die neue Konfiguration verifizieren (nginx -t) und den Webserver die neue Konfiguration übernehmen lassen (systemctl reload nginx.service).

Nextcloud Konfiguration anpassen

Die Nextcloud Instanz ist damit bereits von außen erreichbar. Einziges Problem, auf welches ich leider erst durch nachfragen aufmerksam wurde (hätte man mal die Dokumentation gelesen…): Nextcloud akzeptiert nicht wahllos Proxies, und wenn sich nun ein Client bspw. mit falschem Passwort verbindet greift die integrierte Brute-Force-Protection, wodurch die Verbindung aller Clients gedrosselt wird. Um das zu verhindern muss man innerhalb des Nextcloud Containers die Datei /var/www/html/config/config.php erweitern. Das geht entweder, indem man vom Host aus die Datei bearbeitet (wo das Datenverzeichnis liegt bekommt man via docker volume inspect nextcloud-data heraus), oder alternativ in den Container wechselt und bspw. mittels vi/vim die Datei anpasst:

# docker exec -i -t nextcloud-12 /bin/bash

Wie die Konfiguration erweitert werden muss kann auch in der offiziellen Dokumentation nachgelesen werden, für mich sah das ganze letztlich so aus:

[…]
  "trusted_proxies"   => ['172.17.0.1'],
  "overwritehost"     => "example.org",
  "overwriteprotocol" => "https",
  "overwritewebroot"  => "/",
  "overwritecondaddr" => "^172\.17\.0\.1$",
[…]

Welche IP Adresse man eintragen muss erfährt man via docker network inspect bridge.

Systemd service

Damit der Container nun automatisch bei jedem Systemstart gestartet wird empfiehlt es sich auf dem Host einen entsprechenden Service zu kreieren, dieser wird dann unter /etc/systemd/system/docker-container@.service gespeichert:

[Unit]
Description=Docker Container %I
Requires=docker.service
After=docker.service

[Service]
Restart=always
ExecStart=/usr/bin/docker start -a %i
ExecStop=/usr/bin/docker stop -t 2 %i

[Install]
WantedBy=default.target

Anschließend den Container stoppen und via systemctl aktivieren sowie neu starten:

# docker stop nextcloud-12
# systemctl daemon-reload
# systemctl start docker-container@nextcloud-12.service
# systemctl enable docker-container@nextcloud-12.service

Upgrades

Sollte man den Container irgendwann einmal auf eine neue Version upgraden müssen, geht dies dank Docker und separatem Volume für Daten ganz einfach. Das Upgrade von Version 11 auf die kürzlich erschienene Version 12 lief etwa so ab:

# docker pull nextcloud:12-apache
# systemctl disable docker-container@nextcloud-11.service
# systemctl stop docker-container@nextcloud-11.service
# docker rm nextcloud-11
# docker create -v nextcloud-data:/var/www/html -p 127.0.0.1:32768:80 --name nextcloud-12 nextcloud:12-apache
# systemctl enable docker-container@nextcloud-12.service
# systemctl start docker-container@nextcloud-12.service

Und jetzt?

Damit ist Teil eins, die Einrichtung von Nextcloud, Docker und Nginx, beendet. Weiter geht es mit Teil 2: Der eigentliche Spielspaß (Link wird nachgereicht sobald der Artikel fertig ist). Selbstverständlich bin ich wieder auf allerhand Fehler gestoßen, wie immer wenn ich eine Software auf Herz und Nieren teste.