Nextcloud
- Source: https://github.com/nextcloud/server
- License: AGPL-3
- Alternatives: ownCloud, Seafile, Syncthing
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_domainsis re-applied fromEXIST_DOMAINon every start (abefore-startinghook), so changing the domain doesn't leave Nextcloud on "Access through untrusted domain".overwritehost,overwriteprotocol,overwrite.cli.urlandtrusted_proxiesare read from the environment on every request, so they followEXIST_DOMAINtoo.
On a NAS
Two volumes can live on the NAS (Storage); config, apps, themes and the database stay local.
nextcloud_shareis 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_datais Nextcloud's own layout (<user>/files/,appdata_*,nextcloud.log). GiveEXIST_NFS_PATH_NEXTCLOUD_DATAan 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, notwww-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