Nextcloud

From Leo's Notes
Last edited on 25 April 2023, at 18:36.

Setup

With docker and docker-compose

I use Docker Compose to run my NextCloud instances. This is what my docker-compose.yml setup looks like with Traefik as the reverse proxy.

version: '3.3'

services:
  nextcloud:
    image: nextcloud:latest
    restart: always
    depends_on:
      - db
    environment:
      - UPLOAD_MAX_SIZE=10G
      - MEMORY_LIMIT=2048M
      - TZ=America/Edmonton
      - REDIS_HOST=redis
      - DB_TYPE=mysql
      - DB_NAME=nextcloud
      - DB_USER=nextcloud
      - DB_PASSWORD=*********
      - DB_HOST=db
    labels:
      - traefik.enable=true
      - traefik.docker.network=traefik
      # http
      - traefik.http.routers.nextcloud.entrypoints=http
      - traefik.http.routers.nextcloud.rule=Host(`cloud.example.com`)
      - traefik.http.routers.nextcloud.service=nextcloud
      - traefik.http.services.nextcloud.loadbalancer.server.port=80
      - traefik.http.routers.nextcloud.middlewares=nextcloud-https-redirect
      - traefik.http.middlewares.nextcloud-https-redirect.redirectscheme.scheme=https

      # https
      - traefik.http.routers.nextcloud-https.entrypoints=https
      - traefik.http.routers.nextcloud-https.rule=Host(`cloud.example.com`)
      - traefik.http.routers.nextcloud-https.tls=true
      # - traefik.http.routers.nextcloud-https.tls.certresolver=letsencrypt
      - traefik.http.routers.nextcloud-https.service=nextcloud-https
      - traefik.http.services.nextcloud-https.loadbalancer.server.port=80
      - traefik.http.routers.nextcloud-https.middlewares=nextcloud-redirectregex
      - "traefik.http.middlewares.nextcloud-redirectregex.redirectRegex.regex=https://(.*)/.well-known/(card|cal)dav"
      - "traefik.http.middlewares.nextcloud-redirectregex.redirectRegex.replacement=https://$${1}/remote.php/dav/"
      - "traefik.http.routers.nextcloud-https.middlewares=servicests"
      - "traefik.http.middlewares.servicests.headers.stsincludesubdomains=false"
      - "traefik.http.middlewares.servicests.headers.stspreload=true"
      - "traefik.http.middlewares.servicests.headers.stsseconds=31536000"
      - "traefik.http.middlewares.servicests.headers.isdevelopment=false"
    expose:
      - "80"
    networks:
      - internal
      - traefik
    volumes:
      - nextcloud_data:/data
      - nextcloud_www:/var/www/html
      - /volumes/nextcloud/config:/var/www/html/config
      - /volumes/nextcloud/apps:/var/www/html/custom_apps

  cron:
    image: nextcloud:latest
    restart: always
    volumes:
      - nextcloud_data:/data
      - nextcloud_www:/var/www/html
      - /volumes/nextcloud/config:/var/www/html/config
    entrypoint: /cron.sh
    depends_on:
      - db

  # If using MySQL
  nextcloud-db:
    image: mariadb:latest
    volumes:
      - /volumes/nextcloud/db:/var/lib/mysql
    environment:
      - MYSQL_ROOT_PASSWORD=*********
      - MYSQL_DATABASE=nextcloud
      - MYSQL_USER=nextcloud
      - MYSQL_PASSWORD=*********
      - MARIADB_AUTO_UPGRADE=1
      - MARIADB_INITDB_SKIP_TZINFO=1
    command: --innodb_read_only_compressed=OFF --transaction-isolation=READ-COMMITTED
	# Use binlogs by adding: --log-bin=nextcloud-bin --binlog-format=ROW
    restart: always
    networks:
      - internal

The official Docker image requires root but will spawn Apache as www-data (uid/gid 33). As a result, your custom apps, config, and data files need to be owned by 33:33.

For cron to work, you'll also need to spin up a separate container which runs the crond busybox applet.

Samba support

The official Docker image does not come with libsmbclient installed. External samba storage will not work, as a result. To add in samba, you'll have to use the following Dockerfile to add in samba:

FROM nextcloud:25

RUN set -ex; \
        savedAptMark="$(apt-mark showmanual)"; \
        apt-get update; \
        apt-get install  -y --no-install-recommends  libsmbclient libsmbclient-dev; \
        pecl install smbclient; \
        docker-php-ext-enable smbclient; \
        rm -r /tmp/pear; \
\
        # reset apt-mark's "manual" list so that "purge --auto-remove" will remove all build dependencies
        apt-mark auto '.*' > /dev/null; \
        apt-mark manual $savedAptMark; \
        ldd "$(php -r 'echo ini_get("extension_dir");')"/*.so \
        | awk '/=>/ { print $3 }' \
        | sort -u \
        | xargs -r dpkg-query -S \
        | cut -d: -f1 \
        | sort -u \
        | xargs -rt apt-mark manual; \
\
        apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false; \
        rm -rf /var/lib/apt/lists/*

Management tasks

Management tasks can be done using the occ command. Documentation about this tool can be found at https://docs.nextcloud.com/server/20/admin_manual/configuration_server/occ_command.html

You can run the occ command in the docker container by:

  1. Entering the container with docker exec -ti $container-id
  2. Run su www-data -s /bin/bash to become the www-data user
  3. Run php occ to run the occ script. Eg: php occ db:add-missing-indices

Things that you can do include:

  • php occ files:scan --all
  • php occ files:scan-app-data
  • php occ maintenance:mode --on or php occ maintenance:mode --off

Troubleshooting

Locked File

After an unexpected power loss on a server, a file was stuck in a locked state.

File Locks with Database

To clear any locks if using database file locks:

  1. Log in to the database
  2. Empty the oc_file_locks table with DELETE FROM oc_file_locks WHERE 1.

File Locks with Redis

File locks can also use Redis if enabled in the configuration with:

'memcache.locking' => '\\OC\\Memcache\\Redis',

To clear any locks if using Redis, just stop Redis and remove its dump.rdb file.

Disable File Locking

Alternatively, disable file locks completely by setting config/config.php:

'filelocking.enabled' => false,

Disabling is recommended if you have multiple applications that may be accessing the file at the same time.

See: https://help.nextcloud.com/t/file-is-locked-how-to-unlock/1883

Corruption of an index tree error

I encountered a NextCloud instance which didn't start up properly. Logs show the database connection wasn't working and the MariaDB logs show the following:

2022-11-22  6:32:16 0 [ERROR] InnoDB: Corruption of an index tree: table `nextcloud`.`oc_filecache` index `fs_mtime`, father ptr page no 707081, child page no 708381
PHYSICAL RECORD: n_fields 2; compact format; info bits 0
 0: len 8; hex 800000005848a162; asc     XH b;;
 1: len 8; hex 8000000000e5e3fd; asc         ;;
2022-11-22  6:32:16 0 [Note] InnoDB: n_owned: 0; heap_no: 380; next rec: 8042
PHYSICAL RECORD: n_fields 3; compact format; info bits 0
 0: len 8; hex 800000005847ad89; asc     XG  ;;
 1: len 8; hex 8000000001628161; asc      b a;;
 2: len 4; hex 000aca09; asc     ;;
2022-11-22  6:32:16 0 [Note] InnoDB: n_owned: 0; heap_no: 18; next rec: 2425
2022-11-22  6:32:16 0 [ERROR] [FATAL] InnoDB: You should dump + drop + reimport the table to fix the corruption. If the crash happens at database startup. Please refer to https://mariadb.com/kb/en/library/innodb-recovery-modes/ for information about forcing recovery. Then dump + drop + reimport.
221122  6:32:16 [ERROR] mysqld got signal 6 ;
This could be because you hit a bug. It is also possible that this binary
or one of the libraries it was linked against is corrupt, improperly built,
or misconfigured. This error can also be caused by malfunctioning hardware.

To report this bug, see https://mariadb.com/kb/en/reporting-bugs

We will try our best to scrape up some info that will hopefully help
diagnose the problem, but since we have already crashed,
something is definitely wrong and this may fail.

Fix procedure

This was only fixed after I copied a clean copy of the oc_filecache table files from a clean installation of NextCloud over the broken version.