DB-유

Nextcloud on Synology with Docker

· synology, docker, nextcloud

Cloud Station is fine for syncing my own machines, but it falls over when I have to share something with people outside, or want a WebDAV endpoint. So I ended up running Nextcloud. In Docker on the NAS it stays apart from DSM's own PHP and web server, and upgrading is just an image tag change.

My setup is the official nextcloud image with Apache, a MariaDB container, and Redis for file locking, all in one Compose file. I assume Docker and docker-compose already work over SSH (see my earlier post on Compose), and that you have a DDNS hostname and certificate if you want outside access. The clients insist on HTTPS in practice. Leave plenty of room on the volume too; the data directory holds every synced file.

Step 1: Folders and the Compose file

sudo -i
mkdir -p /volume1/docker/nextcloud/{db,html,data}
cd /volume1/docker/nextcloud
vi docker-compose.yml
version: '2'
services:
  db:
    image: mariadb:10.1
    container_name: nextcloud-db
    restart: unless-stopped
    command: --transaction-isolation=READ-COMMITTED --binlog-format=ROW
    environment:
      MYSQL_ROOT_PASSWORD: rootpw-change-me
      MYSQL_DATABASE: nextcloud
      MYSQL_USER: nextcloud
      MYSQL_PASSWORD: ncpw-change-me
    volumes:
      - /volume1/docker/nextcloud/db:/var/lib/mysql

  redis:
    image: redis:4-alpine
    container_name: nextcloud-redis
    restart: unless-stopped

  app:
    image: nextcloud:12-apache
    container_name: nextcloud-app
    restart: unless-stopped
    depends_on:
      - db
      - redis
    ports:
      - "8088:80"
    environment:
      MYSQL_HOST: db
      MYSQL_DATABASE: nextcloud
      MYSQL_USER: nextcloud
      MYSQL_PASSWORD: ncpw-change-me
    volumes:
      - /volume1/docker/nextcloud/html:/var/www/html
      - /volume1/docker/nextcloud/data:/var/www/html/data

The READ-COMMITTED and ROW options are what the Nextcloud documentation requires for MariaDB. I mount data separately so I can exclude the bulky files from a config-only backup.

Step 2: Start it and finish the installer

docker-compose up -d
docker-compose logs -f app

Wait for Apache's "resuming normal operations" line, then open http://<nas-ip>:8088. Create the admin account. Under "Storage & database" choose MySQL/MariaDB with user nextcloud, the password from the YAML, database nextcloud and host db. Click Finish.

Step 3: Add Redis and trusted domains to config.php

The installer does not know about Redis. Edit the configuration on the host:

vi /volume1/docker/nextcloud/html/config/config.php

Add inside the array:

  'memcache.local' => '\OC\Memcache\APCu',
  'memcache.locking' => '\OC\Memcache\Redis',
  'redis' => array(
    'host' => 'redis',
    'port' => 6379,
  ),
  'trusted_domains' => array(
    0 => '192.168.1.20:8088',
    1 => 'cloud.example.synology.me',
  ),
  'overwriteprotocol' => 'https',

The overwriteprotocol line is needed once you put DSM's reverse proxy in front, otherwise Nextcloud generates http:// links and the desktop client loops on login.

Step 4: Put DSM's reverse proxy in front for HTTPS

Control Panel → Application Portal → Reverse Proxy → Create:

  • Source: HTTPS, hostname cloud.example.synology.me, port 443.
  • Destination: HTTP, localhost, port 8088.

Assign the Let's Encrypt certificate for that hostname under Control Panel → Security → Certificate → Configure. Forward port 443 on the router to the NAS. DSM's nginx now terminates TLS and passes plain HTTP to the container.

Set a cron job for background tasks with DSM's Task Scheduler (Control Panel → Task Scheduler → Create → Scheduled Task → User-defined script, run as root, every 15 minutes):

docker exec -u www-data nextcloud-app php -f /var/www/html/cron.php

Then in Nextcloud's admin settings, switch Background jobs from AJAX to Cron.

Checking it

Log in over https://cloud.example.synology.me. Open Settings → Administration → Basic settings and check that "Last job ran" updates every 15 minutes. Run the built-in check:

docker exec -u www-data nextcloud-app php occ status
docker exec -u www-data nextcloud-app php occ config:system:get memcache.locking

Install the desktop client on a PC, connect, and confirm files appear under /volume1/docker/nextcloud/data/<user>/files/. Those files are not visible in File Station in a useful way; never edit them there, Nextcloud tracks them in the database.

Things that bit me

  • "Access through untrusted domain": the hostname you used is not in trusted_domains. Add it and reload; no restart needed.
  • Large uploads through the web interface fail with "413 Request Entity Too Large": DSM's nginx applies its own client_max_body_size in front of the container. The reverse proxy GUI has no setting for it; the workaround is a custom nginx include such as /usr/local/etc/nginx/conf.d/nextcloud.conf containing client_max_body_size 0; followed by synoservice --restart nginx, and it may need re-applying after DSM updates. The desktop and mobile clients upload in chunks and are not affected.
  • Clients keep asking for the password: overwriteprotocol is missing, so Nextcloud thinks it is serving HTTP.
  • "Your data directory is readable by other users": the data folder was created through File Station with open ACLs. Run chmod 770 /volume1/docker/nextcloud/data and chown -R 33:33 on it (33 is www-data in the image).

Upgrades are docker-compose pull and up -d after bumping the tag one major version at a time; Nextcloud won't let you skip versions, and I learned that by trying. Keep html, data and db in Hyper Backup and the whole thing is portable.