Nextcloud mit nginx und php-fpm installieren

Hier zeige ich euch wie ihr Nextcloud als Docker Container mit nginx und php-fpm einrichtet.

Vorausgesetzt ihr habt bereits Traefik, wie hier beschrieben, am laufen.

1. Verzeichnisse anlegen

Zuerst legen wir uns wieder einige Verzeichnisse und Dateien an, welche wir im Verlauf dieser Anleitung brauchen werden.

mkdir nextcloud-fpm-stack
mkdir nextcloud-fpm-stack/nextcloud
mkdir nextcloud-fpm-stack/db
touch nextcloud-fpm-stack/docker-compose.yml
touch nextcloud-fpm-stack/nginx.conf

2. docker-compose.yml

Wir bearbeiten die docker-compose.yml, ob mit vi, vim oder nano bleibt wieder euch überlassen.

version: '3'

services:
  nginx-nextcloud-fpm:
    image: nginx
    container_name: nginx-nextcloud-fpm
    hostname: example.com
    restart: unless-stopped
    volumes:
        - ./nginx.conf:/etc/nginx/conf.d/nginx.conf:ro
        - ./nextcloud:/var/www/html
    links:
        - nextcloud-fpm
    networks:
        - default
        - proxy
    labels:
        - "traefik.enable=true"
        - "traefik.http.routers.nginx-nextcloud-fpm.entrypoints=http"
        - "traefik.http.routers.nginx-nextcloud-fpm.rule=Host(`nextcloud.example.com`)" ##Domains anpassen##
        - "traefik.http.middlewares.nginx-nextcloud-fpm-https-redirect.redirectscheme.scheme=https"
        - "traefik.http.routers.nginx-nextcloud-fpm.middlewares=nginx-nextcloud-fpm-https-redirect"
        - "traefik.http.routers.nginx-nextcloud-fpm-secure.entrypoints=https"
        - "traefik.http.routers.nginx-nextcloud-fpm-secure.rule=Host(`nextcloud.example.com`)" ##Domains anpassen##
        - "traefik.http.routers.nginx-nextcloud-fpm-secure.tls=true"
        - "traefik.http.routers.nginx-nextcloud-fpm-secure.tls.certresolver=http"
        - "traefik.http.routers.nginx-nextcloud-fpm-secure.service=nginx-nextcloud-fpm"
        - "traefik.http.services.nginx-nextcloud-fpm.loadbalancer.server.port=80"
        - "traefik.docker.network=proxy"
        - "traefik.http.routers.nginx-nextcloud-fpm-secure.middlewares=nginx-nextcloud-fpm-dav,secHeaders@file"
        - "traefik.http.middlewares.nginx-nextcloud-fpm-dav.replacepathregex.regex=^/.well-known/ca(l|rd)dav"
        - "traefik.http.middlewares.nginx-nextcloud-fpm-dav.replacepathregex.replacement=/remote.php/dav/"
        - "traefik.backend=nginx"
        - "traefik.frontend.rule=Host:nextcloud.example.com"  ##Domain anpassen##
        
  nextcloud-fpm-redis:
    image: redis:alpine
    container_name: nextcloud-fpm-redis
    hostname: nextcloud-fpm-redis
    networks:
        - default
    restart: unless-stopped
    command: redis-server --requirepass password ##Redis Passwort eingeben##
    
  nextcloud-fpm:
    image: nextcloud:fpm
    container_name: nextcloud-fpm
    restart: unless-stopped
    depends_on:
      - nextcloud-fpm-db
      - nextcloud-fpm-redis
    environment:
      REDIS_HOST: nextcloud-fpm-redis
      REDIS_HOST_PASSWORD: password ##Redis Passwort von oben wieder eingeben##
      MYSQL_PASSWORD: password ##Hier Passwort eingeben##
      MYSQL_DATABASE: nextcloud
      MYSQL_USER: user ## Hier Benutzer eingeben ##
      MYSQL_HOST: nextcloud-fpm-db
    volumes:
      - ./nextcloud:/var/www/html
    networks:
      - default
    labels:
        - "traefik.enable=false"

  nextcloud-fpm-db:
    image: mariadb
    container_name: nextcloud-fpm-db
    command: --transaction-isolation=READ-COMMITTED --log-bin=ROW --innodb-read-only-compressed=OFF
    restart: unless-stopped
    volumes:
      - /etc/localtime:/etc/localtime:ro
      - /etc/timezone:/etc/timezone:ro
      - ./db:/var/lib/mysql
    environment:
      - MYSQL_ROOT_PASSWORD=password ##SQL root Passwort eingeben##
      - MYSQL_PASSWORD=password ##SQL Benutzer Passwort von oben eingeben##
      - MYSQL_DATABASE=nextcloud ##Datenbank Name von oben eingeben##
      - MYSQL_USER=user #SQL Benutzername von oben eingeben##
      - MYSQL_INITDB_SKIP_TZINFO=1 
    networks:
      - default

  phpmyadmin-nextcloud:
    image: phpmyadmin/phpmyadmin
    container_name: phpmyadmin-nextcloud
    environment:
      PMA_ARBITRARY: 1
    restart: unless-stopped
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.phpmyadmin-nextcloud.entrypoints=http"
      - "traefik.http.routers.phpmyadmin-nextcloud.rule=Host(`phpmyadmin-nextcloud.example.com`)"  ##Domain anpassen##
      - "traefik.http.middlewares.phpmyadmin-nextcloud-https-redirect.redirectscheme.scheme=https"
      - "traefik.http.routers.phpmyadmin-nextcloud.middlewares=phpmyadmin-nextcloud-https-redirect"
      - "traefik.http.routers.phpmyadmin-nextcloud-secure.entrypoints=https"
      - "traefik.http.routers.phpmyadmin-nextcloud-secure.rule=Host(`phpmyadmin-nextcloud.example.com`)" ##Domain anpassen##
      - "traefik.http.routers.phpmyadmin-nextcloud-secure.tls=true"
      - "traefik.http.routers.phpmyadmin-nextcloud-secure.tls.certresolver=http"
      - "traefik.http.routers.phpmyadmin-nextcloud-secure.service=phpmyadmin-nextcloud"
      - "traefik.http.services.phpmyadmin-nextcloud.loadbalancer.server.port=80"
      - "traefik.docker.network=proxy"
      - "traefik.http.routers.phpmyadmin-nextcloud-secure.middlewares=secHeaders@file"
    networks:
      - proxy
      - default

networks:
  proxy:
    external: true

An den Stellen im Code wo die Kommentare sind müsst ihr noch eure Domain anpassen.

Und bei der Konfiguration für die Datenbank müsst ihr User und Passwort ändern, sonst heißt der Datenbank-Benutzer "user" und das Passwort ist dann "password".

3. nginx.conf

Nginx ist unser Webserver, welcher die Seite ausliefert. Der "nextcloud:fpm" Container ist nur rein für php zuständig. Nun brauchen wir also eine Konfiguration für nginx um diesem zu sagen wie er php Dateien behandeln soll.

Wir bearbeiten die Datei nginx.conf.

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

server {
    listen 80;
    server_name nextcloud.example.com;

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

    # HSTS settings
    # 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 Strict-Transport-Security "max-age=15768000; includeSubDomains; preload;" always;

    # set max upload size
    client_max_body_size 512M;
    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;

    # Pagespeed is not supported by Nextcloud, so if your server is built
    # with the `ngx_pagespeed` module, uncomment this line to disable it.
    #pagespeed off;

    # HTTP response headers borrowed from Nextcloud `.htaccess`
    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;

    # Specify how to handle directories -- specifying `/index.php$request_uri`
    # here as the fallback means that Nginx always exhibits the desired behaviour
    # when a client requests a path that corresponds to a directory that exists
    # on the server. In particular, if that directory contains an index.php file,
    # that file is correctly served; if it doesn't, then the request is passed to
    # the front-end controller. This consistent behaviour means that we don't need
    # to specify custom rules for certain paths (e.g. images and other assets,
    # `/updater`, `/ocm-provider`, `/ocs-provider`), and thus
    # `try_files $uri $uri/ /index.php$request_uri`
    # always provides the desired behaviour.
    index index.php index.html /index.php$request_uri;

    # Rule borrowed from `.htaccess` to handle Microsoft DAV clients
    location = / {
        if ( $http_user_agent ~ ^DavClnt ) {
            return 302 /remote.php/webdav/$is_args$args;
        }
    }

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

    # Make a regex exception for `/.well-known` so that clients can still
    # access it despite the existence of the regex rule
    # `location ~ /(\.|autotest|...)` which would otherwise handle requests
    # for `/.well-known`.
    location ^~ /.well-known {
        # The following 6 rules are borrowed from `.htaccess`

        location = /.well-known/carddav     { return 301 /remote.php/dav/; }
        location = /.well-known/caldav      { return 301 /remote.php/dav/; }
        # Anything else is dynamically handled by Nextcloud
        location ^~ /.well-known            { return 301 /index.php$uri; }

        try_files $uri $uri/ =404;
    }

    # Rules borrowed from `.htaccess` to hide certain paths from clients
    location ~ ^/(?:build|tests|config|lib|3rdparty|templates|data)(?:$|/)  { return 404; }
    location ~ ^/(?:\.|autotest|occ|issue|indie|db_|console)              { return 404; }

    # Ensure this block, which passes PHP files to the PHP process, is above the blocks
    # which handle static assets (as seen below). If this block is not declared first,
    # then Nginx will encounter an infinite rewriting loop when it prepends `/index.php`
    # to the URI, resulting in a HTTP 500 error response.
    location ~ \.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;

        fastcgi_param modHeadersAvailable true;         # Avoid sending the security headers twice
        fastcgi_param front_controller_active true;     # Enable pretty urls
        fastcgi_pass php-handler;

        fastcgi_intercept_errors on;
        fastcgi_request_buffering off;
    }

    location ~ \.(?:css|js|svg|gif)$ {
        try_files $uri /index.php$request_uri;
        expires 6M;         # Cache-Control policy borrowed from `.htaccess`
        access_log off;     # Optional: Don't log access to assets
    }

    location ~ \.woff2?$ {
        try_files $uri /index.php$request_uri;
        expires 7d;         # Cache-Control policy borrowed from `.htaccess`
        access_log off;     # Optional: Don't log access to assets
    }

    location / {
        try_files $uri $uri/ /index.php$request_uri;
    }
}

4. Start der Container

Nachdem nun alles fertig konfiguriert ist können wir unsere Container starten.

Dafür geben wir folgenden Befehl ein ...

docker-compose up -d ##Wenn ihr im Verzeichnis nextcloud-fpm-stack befindet, wenn nicht dann##
docker-compose -f ~/nextcloud-fpm-stack/docker-compose.yml up -d

5. Installation von Nextcloud

Nun können wir Nextcloud installieren. Dazu geben wir unsere Domain "nextcloud.example.com" im Browser ein. Wir werden direkt zur Installation geführt.

Gebt einen Benutzernamen und ein Passwort ein.

Dann klickt ihr auf "Installation abschließen".

6. Optimierung

Wenn die Installation durch ist und ihr oben rechts auf euer Avatar, dann Einstellungen und dann links unter Verwaltung auf Übersicht klickt seht ihr folgende Seite:

Wie ihr seht besteht hier noch etwas Optimierungsbedarf. Um Nextcloud also noch ein bisschen zu optimieren gehen wir zunächst in die Datei config.php. Diese befindet sich in "~/nextcloud-fpm-stack/nextcloud/config/config.php".

Da die Datei dem User "www-data" gehört brauchen wir sudo.

sudo vim ~/nextcloud-fpm-stack/nextcloud/config/config.php

Fügt folgende Zeilen am Ende der Datei hinzu ..

'trusted_proxies' => 'traefik',
'overwriteprotocol' => 'https',
'overwritehost' => 'nextcloud.example.com', ##Hier Domain anpassen##
'default_phone_region' => 'DE',

Nachdem ihr das gemacht habt sollten einige der Meldungen verschwunden sein.

Nun richten wir noch einen cronjob für die regelmäßige Ausführung von Hintergrund Aktivitäten ein. Dies dient der weiteren optimierung der Geschwindigkeit.

Dazu gebt ihr folgenden Befehl ein ...

crontab -e

Fügt folgende Zeile am ende der Datei ein ...

*/5 * * * * docker exec -u www-data nextcloud-fpm php cron.php

Danach geht ihr in den Einstellungen unter Verwaltung auf Grundeinstellungen und stellt die Hintergrund-Aufgaben auf Cron.

Nun könnt ihr Nextcloud benutzen ... Viel Spaß.