Nextcloud mit Docker Compose und Traefik

Nextcloud mit Docker Compose und Traefik
Photo by engin akyurt / Unsplash

Nextcloud ist eine Plattform für die Zusammenarbeit im Team, die die Speicherung, den Austausch und die gemeinsame Bearbeitung von Dokumenten ermöglicht. Sie kann durch Erweiterungen zu einer kompletten Groupware ausgebaut werden.

Die Installation kann auf verschiedene Arten erfolgen, sowohl als manuelle Installation aller benötigten Komponenten oder mit Docker Images. In diesem Artikel geht es um die Bereitstellung von Nextcloud ohne zusätzliche Erweiterungen mit Hilfe einer "docker-compose.yml" Datei in meiner HomeLab Umgebung mit Traefik und Portainer.

Neben dem Nextcloud Image benötige ich noch Redis, das empfohlen wird, um Dateisperren zu vermeiden, sowie einer Datenbank von MariaDB. In meiner Docker Umgebung verwende ich die Docker Volumes als permanente Datenspeicher und lege diese automatisch über Docker Compose an. Der Zugriff auf Nextcloud erfolgt über den Reverse Proxy Traefik und seinem externen Docker Netzwerk "proxy". Für den Zugriff wird ein öffentlicher Domainname benötigt. Diesen erhalte ich für mein HomeLab über den kostenlosen, dynamischen DNS Dienst "dynv6".

Für die "docker-compose.yml" habe ich mir die offizielle Nextcloud Compose genommen und diese abgeändert für Traefik.

version: '3.3'

services:
  nextcloud-db:
    image: mariadb:10.6
    container_name: nextcloud-db
    hostname: nextcloud-db
    restart: unless-stopped
    command: --transaction-isolation=READ-COMMITTED --innodb_read_only_compressed=OFF
    volumes:
      - /etc/localtime:/etc/localtime:ro
      - /etc/timezone:/etc/timezone:ro
      - db:/var/lib/mysql  
    environment:
      - MYSQL_ROOT_PASSWORD=${NC_MYSQL_ROOT_PASSWORD}
      - MYSQL_PASSWORD=${NC_MYSQL_USER_PASSWORD}
      - MYSQL_USER=nextcloud
      - MYSQL_DATABASE=nextcloud
      - MYSQL_INITDB_SKIP_TZINFO=1
      - MARIADB_AUTO_UPGRADE=1
    networks:
      - default

  nextcloud-redis:
    image: redis:alpine
    container_name: nextcloud-redis
    hostname: nextcloud-redis
    restart: unless-stopped
    command: redis-server --requirepass ${NC_REDIS_PASSWORD}
    volumes:
      - redis_data:/data
    networks:
      - default

  nextcloud-app:
    image: nextcloud:production
    container_name: nextcloud-app
    hostname: ${NC_APP_DOMAINNAME}
    restart: unless-stopped    
    depends_on:
      - nextcloud-db
      - nextcloud-redis
    volumes:
      - main:/var/www/html
      - data:/var/www/html/data
    environment:
      # Auto configuration
      - MYSQL_PASSWORD=${NC_MYSQL_USER_PASSWORD}
      - MYSQL_USER=nextcloud
      - MYSQL_DATABASE=nextcloud
      - MYSQL_HOST=nextcloud-db
      - NEXTCLOUD_ADMIN_USER=${NC_APP_ADMIN_USER}
      - NEXTCLOUD_ADMIN_PASSWORD=${NC_APP_ADMIN_PASSWORD}
      # Optional email configuration
      - SMTP_HOST=${NC_SMTP_HOST}
      - SMTP_SECURE=ssl
      - SMTP_PORT=465
      - SMTP_AUTHTYPE=LOGIN
      - SMTP_NAME=${NC_SMTP_ACCESS_NAME}
      - SMTP_PASSWORD=${NC_SMTP_ACCESS_PASSWORD}
      - MAIL_FROM_ADDRESS=${NC_MAIL_FROM_NAME}
      - MAIL_DOMAIN=${NC_MAIL_FROM_DOMAIN}
      # Using Redis
      - REDIS_HOST=nextcloud-redis
      - REDIS_HOST_PASSWORD=${NC_REDIS_PASSWORD}
      # Running behind reverse proxy
      - TRUSTED_PROXIES=172.16.255.254/16
      - OVERWRITEPROTOCOL=https
      - OVERWRITECLIURL=https://${NC_APP_DOMAINNAME}
      - OVERWRITEHOST=${NC_APP_DOMAINNAME}      
    labels:
      # Nextcloud https
      - "traefik.enable=true"
      - "traefik.http.routers.nextcloud.rule=Host(`${NC_APP_DOMAINNAME}`)"
      - "traefik.http.routers.nextcloud.entrypoints=websecure"
      - "traefik.http.services.nextcloud.loadbalancer.server.port=80"
      - "traefik.http.routers.nextcloud.service=nextcloud"
      - "traefik.http.routers.nextcloud.tls.certresolver=leresolver"
      - "traefik.docker.network=proxy"
      - "traefik.http.routers.nextcloud.middlewares=nextcloud-dav,nextcloud-sec"
      # Nextcloud webdav 
      - "traefik.http.middlewares.nextcloud-dav.replacepathregex.regex=^/.well-known/ca(l|rd)dav"
      - "traefik.http.middlewares.nextcloud-dav.replacepathregex.replacement=/remote.php/dav/"
      # Nextcloud secHeaders
      - "traefik.http.middlewares.nextcloud-sec.headers.SSLRedirect=true"
      - "traefik.http.middlewares.nextcloud-sec.headers.STSSeconds=315360000"
      - "traefik.http.middlewares.nextcloud-sec.headers.STSIncludeSubdomains=true"
      - "traefik.http.middlewares.nextcloud-sec.headers.STSPreload=true"
      - "traefik.http.middlewares.nextcloud-sec.headers.forceSTSHeader=true"
      - "traefik.http.middlewares.nextcloud-sec.headers.frameDeny=true"
      - "traefik.http.middlewares.nextcloud-sec.headers.customFrameOptionsValue=SAMEORIGIN"
      - "traefik.http.middlewares.nextcloud-sec.headers.contentTypeNosniff=true"
      - "traefik.http.middlewares.nextcloud-sec.headers.browserXSSFilter=true"
      - "traefik.http.middlewares.nextcloud-sec.headers.referrerPolicy=no-referrer"
    networks:
      - proxy
      - default
   
volumes:
  redis_data:
  main:
  data:
  db:
  
networks:
  proxy:
    external: true

In der "docker-compose.yml" sind einige Variablenwerte durch die eigenen Namen, Adressen und Passwörter zu ersetzen. Die Variablen können über eine ".env" Datei im gleichen Ordner oder über Portainer eingelesen werden.

NC_REDIS_PASSWORD=geheim
NC_MYSQL_ROOT_PASSWORD=geheim
NC_MYSQL_USER_PASSWORD=geheim
NC_APP_ADMIN_USER=ncadmin
NC_APP_ADMIN_PASSWORD=geheim
NC_APP_DOMAINNAME=cloud.example.com
NC_SMTP_HOST=smtp.emailprovider.com
NC_SMTP_ACCESS_NAME=cloud@example.com
NC_SMTP_ACCESS_PASSWORD=geheim
NC_MAIL_FROM_NAME=cloud
NC_MAIL_FROM_DOMAIN=example.com

Nach der Bereitstellung von Nextcloud mit Hilfe von "docker compose up -d" oder dem Deployment des Stacks durch Portainer ist die fertige Nextcloud Website zur Anmeldung mit den durch die Variablen vorgegebenem Administrator Account bereit.

Nach der Anmeldung zeigt Nextcloud unter “Einstellungen” - “Übersicht” an, dass es noch "Sicherheits- & Einrichtungswarnungen" gibt.
Sollte die E-Mail Konfiguration über die "docker-compose.yml" genutzt worden sein, entfällt der erste Punkt. Änderungen an der E-Mail Konfiguration über die Grundeinstellungen werden in dem Fall auch nicht akzeptiert und müssen immer über die Variablenwerte erfolgen.

Das Festlegen der Standard-Telefonregion muss leider von der Befehlszeile aus erfolgen. Der Wert für Deutschland ist "DE".

$ docker exec --user www-data -it nextcloud-app php occ config:system:set default_phone_region --value="DE"

Durch das Setzen der für Nextcloud empfohlenen Security Headers in der "docker-compose.yml" für die Middleware von Traefik haben wir eine sehr sichere Website erhalten, wie auch der SSL Test von Qualys bescheinigt - A+.

Zum Schluss muss für Nextcloud noch Cron eingerichtet werden. Im Docker Container werden ansonsten keine Cronjobs ausgeführt. Dazu füge ich mit "crontab -e" auf dem Docker Host in der Crontab für "root" diesen Eintrag hinzu:

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

Diese Zeile bewirkt, dass Docker im Container "nextcloud-app" alle 5 Minuten die “cron.php” Datei ausführt.