12 KiB
Nextcloud in docker
guide-by-example
Purpose & Overview
File share & sync.
Nextcloud is an open source software for sharing files, calendar, general office collaboration stuff. Most people know it and use it as an alternative to onedrive/google drive.
The Nextcloud server is written in PHP and JavaScript. For remote access it employs sabre/dav, an open-source WebDAV server. It is designed to work with most of the databases.
There are many ways to deploy Nextcloud, this setup is going with the most goodies.
Using PHP-FPM
for better performance and using Redis
for more reliable
transactional file locking
and for memory file caching.
Files and directory structure
/home/
└── ~/
└── docker/
└── nextcloud/
├── 🗁 nextcloud_data/
├── 🗁 nextcloud_db_data/
├── 🗋 .env
├── 🗋 docker-compose.yml
├── 🗋 nginx.conf
└── 🗋 nextcloud-backup-script.sh
nextcloud_data/
- users actual data and web app datanextcloud_db_data/
- database data - users and files metadata, configuration.env
- a file containing environment variables for docker composedocker-compose.yml
- a docker compose file, telling docker how to run the containersnginx.conf
- nginx web server configuration filenextcloud-backup-script.sh
- a backup script, to be run daily
You only need to provide the files.
The directories are created by docker compose on the first run.
docker-compose
Official examples here
Five containers to spin up
- nextcloud-app - nextcloud backend app that stores the files and facilitate the sync and runs the apps(calendar, notes, phonetrack,...)
- nextcloud-db - mariadb database storing files-metadata and users-metadata
- nextcloud-web - nginx web server with fastCGI PHP-FPM support
- nextcloud-redis - in memory file caching and more reliable transactional file locking
- nextcloud-cron - for periodic maintenance in the background
Note that nextcloud_data
is mounted in 3 containers.
docker-compose.yml
version: '3'
services:
nextcloud-db:
image: mariadb
container_name: nextcloud-db
hostname: nextcloud-db
command: --transaction-isolation=READ-COMMITTED --binlog-format=ROW --innodb_read_only_compressed=OFF
restart: unless-stopped
env_file: .env
volumes:
- ./nextcloud_data_db:/var/lib/mysql
nextcloud-redis:
image: redis:alpine
container_name: nextcloud-redis
hostname: nextcloud-redis
restart: unless-stopped
nextcloud-app:
image: nextcloud:fpm-alpine
container_name: nextcloud-app
hostname: nextcloud-app
restart: unless-stopped
env_file: .env
depends_on:
- nextcloud-db
- nextcloud-redis
volumes:
- ./nextcloud_data/:/var/www/html
nextcloud-web:
image: nginx:alpine
container_name: nextcloud-web
hostname: nextcloud-web
restart: unless-stopped
volumes:
- ./nextcloud_data/:/var/www/html:ro
- ./nginx.conf:/etc/nginx/nginx.conf:ro
expose:
- 80:80
nextcloud-cron:
image: nextcloud:fpm-alpine
container_name: nextcloud-cron
hostname: nextcloud-cron
restart: unless-stopped
volumes:
- ./nextcloud_data/:/var/www/html
entrypoint: /cron.sh
depends_on:
- nextcloud-db
- nextcloud-redis
networks:
default:
name: $DOCKER_MY_NETWORK
external: true
.env
# GENERAL
DOCKER_MY_NETWORK=caddy_net
TZ=Europe/Bratislava
# NEXTCLOUD-MARIADB
MYSQL_ROOT_PASSWORD=nextcloud
MARIADB_AUTO_UPGRADE=1
MARIADB_DISABLE_UPGRADE_BACKUP=1
MYSQL_PASSWORD=nextcloud
MYSQL_DATABASE=nextcloud
MYSQL_USER=nextcloud
# NEXTCLOUD-APP
MYSQL_HOST=nextcloud-db
REDIS_HOST=nextcloud-redis
OVERWRITEPROTOCOL=https
TRUSTED_PROXIES=caddy
NC_default_phone_region=SK # CHANGE TO YOUR COUNTRY CODE
# USING SENDINBLUE FOR SENDING EMAILS
MAIL_DOMAIN=nextcloud
MAIL_FROM_ADDRESS=nextcloud
SMTP_SECURE=tls
SMTP_HOST=smtp-relay.sendinblue.com
SMTP_PORT=587
SMTP_NAME=<registration-email@gmail.com>
SMTP_PASSWORD=<smtp-key-goes-here>
nginx.conf
Not be pasted here, too long.
It is included in this github repo.
nginx.conf
This is nginx web server configuration file, specifically setup
to support fastCGI PHP-FPM.
From this official nextcloud example
setup
and has one thing changed in it - the upstream hostname from app
to nextcloud-app
upstream php-handler {
server nextcloud-app:9000;
}
All containers must be on the same network.
Which is named in the .env
file.
If one does not exist yet: docker network create caddy_net
Reverse proxy
Nextcloud official documentation regarding reverse proxy.
Caddy v2 is used, details
here.
There are few extra directives here to fix some nextcloud warnings.
Caddyfile
nextcloud.{$MY_DOMAIN} {
header Strict-Transport-Security max-age=31536000;
redir /.well-known/carddav /remote.php/carddav 301
redir /.well-known/caldav /remote.php/caldav 301
redir /.well-known/webfinger /index.php/.well-known/webfinger 301
redir /.well-known/nodeinfo /index.php/.well-known/nodeinfo 301
reverse_proxy nextcloud-web:80
}
First run
Nextcloud needs few moments to start, then there is the initial configuration,
creating admin account.
If database env variables were not used then also the database info
would be required here.
The domain or IP you access nextcloud on this first run is added
to trusted_domains
in config.php
.
Changing the domain later on will throw "Access through untrusted domain" error.
Editing nextcloud_data/config/config.php
and adding the new domain will fix it.
Security & setup warnings
Nextcloud has a status check in Settings > Administration > Overview
There could be some warnings there, but if following this guide, it should be
all good. As Caddyfile
and .env
file should take care of it.
Here
is a link to an older commit that talks in more detail on possible stuff here.
But fuck writing on that noise when nextcloud is now doing phone number area
code notification there.
Troubleshooting
- moving between docker hosts, might need to take ownership of directories
exec in tonextcloud-app
;/var/www/html
;chown www-data:www-data *
Extra info
check if redis container works
At https://<nexcloud url>/ocs/v2.php/apps/serverinfo/api/v1/info
ctrl+f for redis
, if it's present it means nexcloud is set to use it.
You can also exec in to redis container:
docker exec -it nextcloud-redis /bin/sh
- start monitoring:
redis-cli MONITOR
- start browsing files on the nextcloud
- there should be activity in the monitoring
check if cron container works
- after letting Nextcloud run for a while
- in settings > administration > basic settings
- background jobs should be set to Cron
- the last job info should never be older than 10 minutes
Update
Manual image update:
docker-compose pull
docker-compose up -d
docker image prune
Updates tend to be problematic with Nexcloud. Inestigating what went wrong in between major version updates... have backups before doing update. And have the god damn tags on docker images.
Backup and restore
Backup
Using kopia or borg to make daily snapshot of the entire docker directory.
Restore
- down the containers
docker-compose down
- delete/move/rename the entire project directory
- from the backups copy back the entire project directory
- start the containers
docker-compose up -d
Backup of just user data
User's data daily export going by the
official procedure.
For nextcloud it means entering the maintenance mode, doing a database dump
and backing up several directories containing data, configs, themes.
Daily kopia/borg backup run takes care of backing up the directories.
So only database dump is needed and done with the script.
Create a backup script
Placed inside nextcloud
directory on the host.
nextcloud-backup-script.sh
#!/bin/bash
# MAINTENANCE MODE ON
docker container exec --user www-data --workdir /var/www/html nextcloud-app php occ maintenance:mode --on
# CREATE DATABASE DUMP, bash -c '...' IS USED OTHERWISE OUTPUT > WOULD TRY TO GO TO THE HOST
docker container exec nextcloud-db bash -c 'mysqldump --single-transaction -h nextcloud-db -u $MYSQL_USER -p$MYSQL_PASSWORD $MYSQL_DATABASE > /var/lib/mysql/BACKUP.nextcloud.database.sql'
# MAINTENANCE MODE OFF
docker container exec --user www-data --workdir /var/www/html nextcloud-app php occ maintenance:mode --off
The script must be executable - chmod +x nextcloud-backup-script.sh
Test run the script sudo ./nextcloud-backup-script.sh
The resulting database dump is in
nextcloud/nextcloud_data_db/BACKUP.nextcloud.database.sql
Cronjob
Running on the host, so that the script will be periodically run.
su
- switch to rootcrontab -e
- add new cron job0 23 * * * /home/bastard/docker/nextcloud/nextcloud-backup-script.sh
runs it every day at 23:00crontab -l
- list cronjobs to check
Restore the user data
Assuming clean start.
- start the containers:
docker-compose up -d
let them run so they create the file structure - down the containers:
docker-compose down
- delete the directories
config
,data
,themes
in the freshly creatednextcloud/nextcloud_data/
- from the backup of
/nextcloud/nextcloud_data/
, copy the directoriesconfigs
,data
,themes
in to the new/nextcloud/nextcloud_data/
- from the backup of
/nextcloud/nextcloud_data_db/
, copy the backup database namedBACKUP.nextcloud.database.sql
in to the new/nextcloud/nextcloud_data_db/
- start the containers:
docker-compose up -d
- set the correct user ownership of the directories copied:
docker exec --workdir /var/www/html nextcloud-app chown -R www-data:www-data config data themes
- restore the database
docker exec --workdir /var/lib/mysql nextcloud-db bash -c 'mysql -u $MYSQL_USER -p$MYSQL_PASSWORD $MYSQL_DATABASE < BACKUP.nextcloud.database.sql'
- turn off the maintenance mode:
docker container exec --user www-data --workdir /var/www/html nextcloud-app php occ maintenance:mode --off
- update the systems data-fingerprint:
docker exec --user www-data --workdir /var/www/html nextcloud-app php occ maintenance:data-fingerprint
- restart the containers:
docker-compose restart
- log in