_Swarm Original Nextcloud:FPM

Änderungsstand: 2021-11-19

Das eigentliche „Nonplusultra“, wenn es darum geht, eine Nextcloudinstallation via Docker zu realisieren. Nextcloud-FPM, MariaDB, Redis, einen eigenen Nginx-Webserver und einen eingebauten Cron-Job, als Anwendung im Swarm Mode. Meine angelegte NFS-Freigabe für das Datenverzeichnis ist /mnt/data/… Im Gegensatz zur normalen Docker-Compose, kann Portainer bzw. der zu erstellende Service, keine Verzeichnisse selbst anlegen. In diesem Fall lege ich die benötigten Verzeichnisse selbst an.

Nicht vergessen, die Pfade, am ersten Manager, anzulegen!

sudo mkdir -p /mnt/data/nextcloudfpm && sudo mkdir -p /mnt/data/nextcloudfpm/nextcloudfpm_db && sudo mkdir -p /mnt/data/nextcloudfpm/nextcloudfpm_data && sudo mkdir -p /mnt/data/nextcloudfpm/nginx
sudo nano /mnt/data/nextcloudfpm/nginx/nginx.conf

Folgendes komplett einfügen (wurde auf dem darauffolgenden Stack angepasst) :

worker_processes auto;

error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;


events {
    worker_connections  1024;
}


http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    keepalive_timeout  65;

    #gzip  on;

    upstream php-handler {
        server nextcloud-app:9000;
    }

    server {
        listen 80;

        # Add headers to serve security related headers
        # Before enabling Strict-Transport-Security headers please read into this
        # topic first.
        #add_header Strict-Transport-Security "max-age=15768000; includeSubDomains; preload;" always;
        #
        # WARNING: Only add the preload option once you read about
        # the consequences in https://hstspreload.org/. This option
        # will add the domain to a hardcoded list that is shipped
        # in all major browsers and getting removed from this list
        # could take several months.
        add_header Referrer-Policy "no-referrer" always;
        add_header X-Content-Type-Options "nosniff" always;
        add_header X-Download-Options "noopen" always;
        add_header X-Frame-Options "SAMEORIGIN" always;
        add_header X-Permitted-Cross-Domain-Policies "none" always;
        add_header X-Robots-Tag "none" always;
        add_header X-XSS-Protection "1; mode=block" always;

        # Remove X-Powered-By, which is an information leak
        fastcgi_hide_header X-Powered-By;

        # Path to the root of your installation
        root /var/www/html;

        location = /robots.txt {
            allow all;
            log_not_found off;
            access_log off;
        }

        # The following 2 rules are only needed for the user_webfinger app.
        # Uncomment it if you're planning to use this app.
        #rewrite ^/.well-known/host-meta /public.php?service=host-meta last;
        #rewrite ^/.well-known/host-meta.json /public.php?service=host-meta-json last;

        # The following rule is only needed for the Social app.
        # Uncomment it if you're planning to use this app.
        #rewrite ^/.well-known/webfinger /public.php?service=webfinger last;

        location = /.well-known/carddav {
            return 301 $scheme://$host:$server_port/remote.php/dav;
        }

        location = /.well-known/caldav {
            return 301 $scheme://$host:$server_port/remote.php/dav;
        }

        # set max upload size
        client_max_body_size 10G;
        fastcgi_buffers 64 4K;

        # Enable gzip but do not remove ETag headers
        gzip on;
        gzip_vary on;
        gzip_comp_level 4;
        gzip_min_length 256;
        gzip_proxied expired no-cache no-store private no_last_modified no_etag auth;
        gzip_types application/atom+xml application/javascript application/json application/ld+json application/manifest+json application/rss+xml application/vnd.geo+json application/vnd.ms-fontobject application/x-font-ttf application/x-web-app-manifest+json application/xhtml+xml application/xml font/opentype image/bmp image/svg+xml image/x-icon text/cache-manifest text/css text/plain text/vcard text/vnd.rim.location.xloc text/vtt text/x-component text/x-cross-domain-policy;

        # Uncomment if your server is build with the ngx_pagespeed module
        # This module is currently not supported.
        #pagespeed off;

        location / {
            rewrite ^ /index.php;
        }

        location ~ ^\/(?:build|tests|config|lib|3rdparty|templates|data)\/ {
            deny all;
        }
        location ~ ^\/(?:\.|autotest|occ|issue|indie|db_|console) {
            deny all;
        }

        location ~ ^\/(?:index|remote|public|cron|core\/ajax\/update|status|ocs\/v[12]|updater\/.+|oc[ms]-provider\/.+)\.php(?:$|\/) {
            fastcgi_split_path_info ^(.+?\.php)(\/.*|)$;
            set $path_info $fastcgi_path_info;
            try_files $fastcgi_script_name =404;
            include fastcgi_params;
            fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
            fastcgi_param PATH_INFO $path_info;
            # fastcgi_param HTTPS on;

            # Avoid sending the security headers twice
            fastcgi_param modHeadersAvailable true;

            # Enable pretty urls
            fastcgi_param front_controller_active true;
            fastcgi_pass php-handler;
            fastcgi_intercept_errors on;
            fastcgi_request_buffering off;
        }

        location ~ ^\/(?:updater|oc[ms]-provider)(?:$|\/) {
            try_files $uri/ =404;
            index index.php;
        }

        # Adding the cache control header for js, css and map files
        # Make sure it is BELOW the PHP block
        location ~ \.(?:css|js|woff2?|svg|gif|map)$ {
            try_files $uri /index.php$request_uri;
            add_header Cache-Control "public, max-age=15778463";
            # Add headers to serve security related headers (It is intended to
            # have those duplicated to the ones above)
            # Before enabling Strict-Transport-Security headers please read into
            # this topic first.
            #add_header Strict-Transport-Security "max-age=15768000; includeSubDomains; preload;" always;
            #
            # WARNING: Only add the preload option once you read about
            # the consequences in https://hstspreload.org/. This option
            # will add the domain to a hardcoded list that is shipped
            # in all major browsers and getting removed from this list
            # could take several months.
            add_header Referrer-Policy "no-referrer" always;
            add_header X-Content-Type-Options "nosniff" always;
            add_header X-Download-Options "noopen" always;
            add_header X-Frame-Options "SAMEORIGIN" always;
            add_header X-Permitted-Cross-Domain-Policies "none" always;
            add_header X-Robots-Tag "none" always;
            add_header X-XSS-Protection "1; mode=block" always;

            # Optional: Don't log access to assets
            access_log off;
        }

        location ~ \.(?:png|html|ttf|ico|jpg|jpeg|bcmap|mp4|webm)$ {
            try_files $uri /index.php$request_uri;
            # Optional: Don't log access to other assets
            access_log off;
        }
    }
}

Strg-x, y, Enter

Quelle:

https://raw.githubusercontent.com/DoTheEvo/selfhosted-apps-docker/master/nextcloud/nginx.conf

Im Portainer:

  • Stacks
    • + Add stack
      • Name: ncfpm
      • Web editor: Folgenden Code eingeben:
version: '3.7'

services:

  nextcloud-db:
    image: lscr.io/linuxserver/mariadb
    environment:
      - PUID=1000
      - PGID=1000
      - MYSQL_ROOT_PASSWORD=PASSWORT123 #SQL root Passwort eingeben
      - MYSQL_PASSWORD=PASSWORT456 #SQL Benutzer Passwort eingeben
      - MYSQL_DATABASE=nextcloud #Datenbank Name
      - MYSQL_USER=nextcloud #SQL Nutzername
      - TZ=Europe/Berlin
    volumes:
      - /mnt/data/nextcloudfpm/nextcloudfpm_db:/var/lib/mysql
    deploy:
      mode: replicated
      replicas: 1
      placement:
        constraints: [node.role == worker]
      restart_policy:
        condition: any
    networks:
      - ncfpm_network

  nextcloud-redis:
    image: arm64v8/redis
    command: redis-server --requirepass PASSWORT789 # Redis Passwort
    deploy:
      mode: replicated
      replicas: 1
      placement:
        constraints: [node.role == manager]
      restart_policy:
        condition: any
    networks:
      - ncfpm_network

  nextcloud-app:
    image: nextcloud:fpm
    depends_on:
      - nextcloud-db
      - nextcloud-redis
    environment:
      - REDIS_HOST=nextcloud-redis
      - REDIS_HOST_PASSWORD=PASSWORT789 # Redis Passwort von oben
      - MYSQL_PASSWORD=PASSWORT456      # SQL Benutzer Passwort (identisch zu Oben)
      - MYSQL_DATABASE=nextcloud        # Datenbank Name (identisch zu Oben)
      - MYSQL_USER=nextcloud            # SQL Nutzername (identisch zu Oben)
      - MYSQL_HOST=nextcloud-db
    volumes:
      - /mnt/data/nextcloudfpm/nextcloudfpm_data/:/var/www/html
    deploy:
      mode: replicated
      replicas: 1
      placement:
        constraints: [node.role == manager]
      restart_policy:
        condition: any
    networks:
      - ncfpm_network

  nextcloud-web:
    image: nginx
    restart: unless-stopped
    ports:
      - 8088:80
    volumes:
      - /mnt/data/nextcloudfpm/nextcloudfpm_data/:/var/www/html:ro
      - /mnt/data/nextcloudfpm/nginx/nginx.conf:/etc/nginx/nginx.conf:ro
    deploy:
      mode: replicated
      replicas: 1
      placement:
        constraints: [node.role == manager]
      restart_policy:
        condition: any
    networks:
      - ncfpm_network

  nextcloud-cron:
    image: nextcloud:fpm
    restart: unless-stopped
    volumes:
      - /mnt/data/nextcloudfpm/nextcloudfpm_data/:/var/www/html
    entrypoint: /cron.sh
    depends_on:
      - nextcloud-db
      - nextcloud-redis
    deploy:
      mode: replicated
      replicas: 1
      placement:
        constraints: [node.role == manager]
      restart_policy:
        condition: any
    networks:
      - ncfpm_network

networks:
  ncfpm_network:
    driver: overlay
    attachable: true

Actions: Deploy the stack

Das Erstellen dauert jetzt etwas. 10 Minuten oder länger sind keine Seltenheit.

Aufruf im Browser: Server-IP:8088

Erscheint die Fehlermeldung „Bad Gateway“, ist noch etwas Zeit für die Initialisierung nötig. Hier paar Minuten warten und anschließend Strg-F5 um die Seite neu zu laden.

Nun ein Administrator-Konto anlegen und „Installation abschließen“ klicken. Die Installation beginnt.

Erscheint eine Fehlermeldung „Bad Gateway“ oder „504 Gateway Time-out“, einfach noch etwas warten (ein kleiner Kaffee regelt 🙂 ) und anschließend die Adresse noch einmal eingeben.

Bei einem meiner vielen Versuche musste ich ein neues Admin-Kennwort eingeben und die Installation nochmals durchführen. Der anschließende Login funktionierte aber nur mit dem ersten erstellten Admin-Zugang.

Nextcloud wird gestartet. Falls kein Login möglich ist, kann das durchaus an einer Einstellung des Browsers liegen. Der Google-Browser z.B. lässt mitunter kein ungesichertes Login zu. Ich hatte das aber ebenfalls nur bei einem meiner Versuche. Abhilfe schafft z.B. der Edge-Browser. Warum gibt es dieses Problem, welches offenkundig mit linuxserver/nextloud nicht besteht? Nun, linuxserver/nextcloud hat seine Sachen schon im Vorfeld verschlüsselt, wenn auch über ein selbssigniertes Zertifikat. Bei der Standard-Nextcloudversion ist die Datenübertragung komplett über http geregelt. Doch ist das nun schlimm? Nicht unbedingt. Verwendet man Nextcloud nur intern, spielt es eigentlich keine große Rolle und verwendet man Nextcloud mit Zugriff von Außen, indem man einen Reverse-Proxy vorschaltet, ist automatisch alles, was beim Reverse-Proxy ankommt verschlüsselt und der Rest, quasi der interne Verkehr läuft zwar unverschlüsselt, aber davon bekommt der Besucher nichts mit, weil das der Reverse-Proxy regelt. Das ist dann am Ende auch der Grund, dass man gewisse „Sicherheits- & Einrichtungswarnungen“, für den reinen internen Betrieb, nicht wegbekommt.

Jetzt noch:

sudo chown -R www-data:www-data /mnt/data/nextcloudfpm

Wer nun Nextcloud nicht für den Zugriff von Außen benötigt, ist hier fertig. Redis wurde, aufgrund der erstellten Konfiguration, wie ich sie wählte, schon eingebunden und bedarf keiner weiteren Nachkonfiguration.

Nextcloud von Außen erreichbar machen:

Zuerst benötigt man im Idealfall mind. einen DynDNS-Dienst, welcher mit Subdomains umgenen kann. DuckDNS und DynDNSS, als Beispiele aufgezählt, können das. NoIP kann das in der kostenlosen Version NICHT! Anschließend benötigt man einen Reverse-Proxy. Ich verwende dafür „Nginx Proxy Manager“. Hier noch einmal die Guides dazu:

DynDNS (DuckDNS) | Nginx Proxy Manager

Info: Portweiterleitung des Routers zum Nginx Proxy Manager nicht vergessen. In meinem Beispiel ist das die Portweiterleitung zum ersten Manager-Node, egal, auf welchem Node sich am Ende NPM befindet. Der Cluster-Swarm-Manager regelt das.

Wurden beide Guides abgearbeitet, richte ich nun Nginx Proxy Manager ein. Dazu diesen im Browser starten. Dann in der „NginX Proxy Manager“ Weboberfläche:

  • „Host“
    • „Proxy Host“
      • „Add Proxy Host“
        • Details:
          • Domain Names: nextclouddrei.clusterfarm.duckdns.org
            • (Eigene Domain verwenden)
          • Scheme: http
            • (8088 ist ein HTTP-Port)
          • Forward Hostname / IP: 192.168.1.141 (erster Manager-Node)
            • (in diesem Beispiel der erste Manager (node1))
          • Forward Port: 8088
          • (8088 ist mein Nextcloud – Port bzw. in dieser Konfiguration der Webserver-Port)
          • Cache Assets: On
          • Websockets Support: On
          • Block Common Exploits: On
          • Access List: nichts ändern
        • SSL:
          • SSL Certificate: „Request a new SSL Certificate“
          • Force SSL: On
          • Http/2 Support: On
          • HSTS Enabled: ON
          • Email Address for Lets‘ Encrypt: Eine gültige Email-Adresse
          • I Agree to the LE Terms of Service: On
        • Advanced:
location ^~ /.well-known {
location = /.well-known/carddav     { return 301 /remote.php/dav/; }
location = /.well-known/caldav      { return 301 /remote.php/dav/; }
location ^~ /.well-known            { return 301 /index.php$uri; }
try_files $uri $uri/ =404;
  }

Save

Nach ca. 10-20 Sekunden wurde das Zertifikat erstellt und der Dienst Nextcloud ist unter der angewendeten Domain, gesichert, von Außen erreichbar. Nextcloud kann nun unter der erstellten Domain geöffnet werden. Und siehe da – Eine Fehlermeldung (Zugriff über eine nicht vertrauenswürdige Domain). Doch diese ist schnell behoben:

sudo nano /mnt/data/nextcloudfpm/nextcloudfpm_data/config/config.php

Zuerst erweitere ich die „trusted_domains“, indem ich den Eintrag 1 => hinzufüge

'trusted_domains' =>
array (
  0 => '192.168.1.141:8084',
  1 => 'nextclouddrei.clusterfarm.duckdns.org',
),

Dann ändere ich „overwrite.cli.url“ ab und füge die restl. Sachen dahinter ein (trusted_proxies ist, für das Beispiel, meine IP des Nginx Proxy Managers, in diesem Fall des ersten Manager-Nodes):

'overwrite.cli.url' => 'https://nextcloudzwei.clusterfarm.duckdns.org',
'overwriteprotocol' => 'https',
'overwritehost' => 'nextclouddrei.clusterfarm.duckdns.org',
'default_phone_region' => 'DE',
'default_language' => 'de',
'force_language' => 'de',
'default_locale' => 'de_DE',
'force_locale' => 'de_DE',
'trusted_proxies' => '192.168.1.141:80',
'forwarded_for_headers' => ['HTTP_X_FORWARDED', 'HTTP_FORWARDED_FOR'],

Strg-x, y, Enter

Browserfenster aktualisieren und Nextcloud ist über die Domain verfügbar. Außer „php-imagick“ sind auch alle Warnhinweise verschwunden.

Quelle:

https://hub.docker.com/_/nextcloud

Erstelle eine Website wie diese mit WordPress.com
Jetzt starten