Skip to main content

Nextcloud

File sharing and sync — Dropbox/Google Drive alternative.

Nextcloud ships with its own Redis (nextcloud-redis), in the same compose file — there is nothing to enable separately. See Cache below.

Setup​

  • Most environment variables are read only on the first start. Set them before then.
  • trusted_domains is re-applied from EXIST_DOMAIN on every start (a before-starting hook), so changing the domain doesn't leave Nextcloud on "Access through untrusted domain".
  • overwritehost, overwriteprotocol, overwrite.cli.url and trusted_proxies are read from the environment on every request, so they follow EXIST_DOMAIN too.

On a NAS​

Two volumes can live on the NAS (Storage); config, apps, themes and the database stay local.

  • nextcloud_share is the share of files you already have. Nextcloud shows it in Files as /nas, a Local external storage for every user, read and written in place over NFS.
  • nextcloud_data is Nextcloud's own layout (<user>/files/, appdata_*, nextcloud.log). Give EXIST_NFS_PATH_NEXTCLOUD_DATA an empty folder, never your share: its own files would land among yours.

Both folders are made by you, owned by EXIST_PUID:EXIST_PGID. Changes made on the NAS show up when someone opens the folder (filesystem_check_changes); nothing rescans /nas on a timer. Without a NAS, /nas is an empty folder under volumes/.

Cache​

nextcloud-redis (redis:8.10.1-alpine3.23, licensed RSALv2 / SSPLv1 / AGPLv3; for commercial hosting pick AGPLv3 or RSALv2):

  • Nextcloud's file locking, distributed cache and PHP sessions. Required, so it lives in Nextcloud's compose file.
  • Only Nextcloud uses it; other services have their own redis.
  • No volume (--save ""). Losing it costs a re-login. Nothing to back up.
  • No maxmemory: at its 128M limit Docker restarts it.

--requirepass is always on, from NEXTCLOUD_REDIS_PASSWORD in nas/nextcloud/.env — one key read by both containers, so the two sides cannot drift. A bare redis-cli ping therefore returns NOAUTH, not PONG; pass -a (see the healthcheck in nas/nextcloud/docker-compose.exist.yml, and nas/nextcloud/exist.test.sh for a dependency-free AUTH+PING over the raw protocol).

Housekeeping​

Any occ command can be run from the host:

docker exec nextcloud php /var/www/html/occ <command>

Migrate mimetypes (after major updates)​

docker exec nextcloud php /var/www/html/occ maintenance:repair --include-expensive

Add missing indices (after major updates)​

docker exec nextcloud php /var/www/html/occ db:add-missing-indices

Background jobs​

nextcloud-cron runs cron.php every minute and delivers webhooks; its first run switches Basic settings from AJAX to Cron. Nothing to add to the host's crontab.

Set maintenance window (UTC)​

docker exec nextcloud php /var/www/html/occ config:system:set maintenance_window_start --type=integer --value=8

The workspace folder​

hooks/before-starting/02-workspace.sh mounts the workspace_data volume as a Local external storage at /workspace, applicable to every user. Sync that folder with the desktop client and you are editing the same tree code-server and decree see. See Getting Started → Workspace.

  • Nextcloud runs as EXIST_PUID, not www-data, because every writer of the volume must be the same uid.
  • Workspace automations don't need Nextcloud: File Handlers see every change. Uploads anywhere in Nextcloud can also fire a file event: File Processor.

Collabora (office document editing)​

./existential.sh flow on office-documents installs the richdocuments app, points it at Collabora, sets wopi_callback_url to http://nextcloud so Collabora fetches files over the exist network, and limits wopi_allowlist to the exist subnet (blank would allow any IP).

To do it by hand instead:

docker exec nextcloud php /var/www/html/occ app:install richdocuments
docker exec nextcloud php /var/www/html/occ config:app:set richdocuments wopi_url \
--value="https://collabora.<domain>"
docker exec nextcloud php /var/www/html/occ config:app:set richdocuments wopi_callback_url \
--value="http://nextcloud"
docker exec nextcloud php /var/www/html/occ config:app:set richdocuments wopi_allowlist \
--value="172.16.0.0/12"

Collabora's own admin console lives at https://collabora.<domain>, gated by COLLABORA_USERNAME/COLLABORA_PASSWORD (nas/collabora/.env).

Calendar​

CalDAV is always on; the Calendar app (/apps/calendar) isn't. ./existential.sh flow on calendar installs it.

To do it by hand instead:

docker exec nextcloud php /var/www/html/occ app:install calendar

Searchable, answerable by pi​

The flow's calendar-extract cron writes each event, from the recent past to CALENDAR_EXTRACT_FUTURE_DAYS ahead, as a note in workspace/ai/calendar/<calendar>/. qmd indexes it (the search flow), so pi can answer "what's on my calendar".

  • Full refresh: a cancelled event's note disappears on the next run.
  • CalDAV details: automation/plugins/calendar_extract.md (tested on nextcloud:34.0.3, recurring events included).

Maintenance​

# Enter maintenance mode
docker exec nextcloud php /var/www/html/occ maintenance:mode --on

# Exit maintenance mode
docker exec nextcloud php /var/www/html/occ maintenance:mode --off

Nextcloud's update check and survey_client app are off (the check sends install time, PHP version and user count). hooks/before-starting/03-no-phone-home.sh re-applies this on every start. To update, bump the image tag in docker-compose.exist.yml.

Restart order​

Only when nextcloud_data is on the NAS: the NAS first, then Nextcloud. Compose mounts the export when the container starts, so a NAS that is down stops Nextcloud from starting; start it again once the NAS is up.

Debugging​

# Check pending background jobs
docker exec -it nextcloud-db mariadb -u root -p nextcloud \
-e "SELECT COUNT(*) FROM oc_jobs WHERE last_run = 0;"

# Manually run cron
time docker exec nextcloud php /var/www/html/cron.php