KopfKrieg Logo
Kann Spuren von Wahnsinn enthalten

Menü

2017-07-12

Nextcloud Teil 1.5: Setup mit Docker, Nginx & PostgreSQL

Wer meine Artikel verfolgt dürfte wissen, dass ich vor knapp einem Monat bereits einen ähnlichen Artikel veröffentlich habe: Nextcloud Teil 1: Setup mit Docker & Nginx. Zu damaliger Zeit dachte ich, dass eine Installation mit SQLite als Datenbank vollkommen ausreichen würde. Und das tat es auch, bis ich dann eines Tages beschloss tausende kleiner Dateien gleichzeitig hochzuladen, einen Feedreader zu installieren und auch sonst die Datenbank bis aufs Äußerste zu belasten. Kurzum: Die Schwuppdizität leidete massiv darunter, was wiederum zu, äh, interessantem Fehlverhalten von Nextcloud führe. Anders gesagt: Ich wusste, ich brauche jetzt doch einen Datenbankserver.

Zusammengefasst entspricht dieser Artikel also fast 1:1 meinem vorherigen Artikel zu diesem Thema, nur dass hier zusätzlich noch PostgreSQL mit aufgesetzt wird. Daher lasse ich auch großartige Erläuterungen weg, wer genaueres wissen will kann diese ja im obig verlinkten Artikel nachlesen.

Docker installieren

# 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"
# apt-get update
# apt-get install docker

PostgreSQL herunterladen & instanziieren

# docker pull postgres:9.6-alpine
# docker volume create --name postgres-data
# docker create -v postgres-data:/var/lib/postgresql/data -e POSTGRES_USER=nextcloud -e POSTGRES_PASSWORD='Password' -e POSTGRES_DB=nextcloud -p 5432:5432 --name postgres-9_6 postgres:9.6-alpine
Wichtig: Ich weiß nicht wieso, aber wenn man den Nutzer oder den Datenbanknamen auf postgres setzt (bzw. die Variablen nicht setzt, da der Standard "postgres" ist), fliegt das ganze – warum auch immer – auf die Fresse. Da müsste mal jemand™ einen Bugreport eröffnen oder dem nachgehen.

Nextcloud herunterladen & instanziieren

# docker pull nextcloud:12-apache
# docker volume create --name nextcloud-postgres-data
# docker create -v nextcloud-postgres-data:/var/www/html -p 32768:80 --name nextcloud-postgres-12 nextcloud:12-apache

Nginx als Proxy konfigurieren

Den „server“-Abschnitt der nginx.conf wie folgt erweitern/ändern:
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, because we don't want a host lookup
    }
}
Dann noch speichern, die neue Konfiguration verifizieren („nginx -t“) und den Webserver die neue Konfiguration übernehmen lassen („systemctl reload nginx.service“).

Systemd service erstellen

Eine Datei /etc/systemd/system/docker-container@.service erstellen und mit folgendem Inhalt füllen:
[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

PostgreSQL & Nextcloud via systemctl starten

# systemctl enable docker-container@postgres-9_6.service
# systemctl enable docker-container@nextcloud-postgres-12.service
# systemctl start docker-container@postgres-9_6.service
# systemctl start docker-container@nextcloud-postgres-12.service

Cron aktivieren

Den Teil hatte ich letztes Mal auch nicht drin, daher eine kurze Erläuterung: Nextcloud läuft im Prinzip ohne Cron via Ajax. An sich 'ne coole Sache, einziges Problem dabei: Nicht alles lässt sich via Ajax machen. Also habe ich das einfachste gemacht was man machen kann: Den Cron-Service des Hosts dazu missbraucht um im Nextcloud-Docker-Container alle 15 Minuten cron.php laufen zu lassen. Muss auf dem Host wie folgt eingerichtet werden:
echo "*/15 *   * * *   root    /usr/bin/docker exec nextcloud-postgres-12 su - www-data -s /bin/bash -c 'php -f /var/www/html/cron.php'" >> /etc/crontab

Nextcloud konfigurieren

Im Browser die Instanz aufrufen, dabei wieder Nutzername und Passwort vergeben. Bei Datenbank natürlich PostgreSQL auswählen und die Daten eingeben. Unter Host:Port muss man die interne IP angeben, diese lässt sich mittels „docker network inspect bridge“ herausfinden. Sah bei mir dann so aus: 172.17.0.2:5432

Nginx als Proxy eintragen

Und zu guter Letzt noch Nginx als Proxy eintragen, weil sonst die Brute-Force-Protection nur localhost als Client-IP sieht und ratet mal, wie schnell das nach hinten losgeht…

Wo die Datei auf dem Host liegt bekommt man mittels „docker volume inspect nextcloud-postgres-data“ heraus, darin muss dann die Datei config/config.php erweitert werden:
[…]
  '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“.

Fertig.

Damit wäre alles fertig eingerichtet. Als nächstes folgt dann Teil 2 (d.h., eigentlich ja Teil 3…). Wenn dieser fertig ist reiche hier im Artikel den Link natürlich nach.