selfhosted-apps-docker/nextcloud/readme.md

359 lines
12 KiB
Markdown

# Nextcloud in docker
###### guide-by-example
![logo](https://i.imgur.com/VXSovC9.png)
# Purpose & Overview
File share & sync.
* [Official site](https://nextcloud.com/)
* [Github](https://github.com/nextcloud/server)
* [DockerHub](https://hub.docker.com/_/nextcloud/)
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.</br>
Using [PHP-FPM](https://www.cloudways.com/blog/php-fpm-on-cloud/)
for better performance and using [Redis](https://aws.amazon.com/redis/)
for more reliable
[transactional file locking](https://docs.nextcloud.com/server/latest/admin_manual/configuration_files/files_locking_transactional.html)
and for [memory file caching](https://docs.nextcloud.com/server/latest/admin_manual/configuration_server/caching_configuration.html).
# 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 data
* `nextcloud_db_data/` - database data - users and files metadata, configuration
* `.env` - a file containing environment variables for docker compose
* `docker-compose.yml` - a docker compose file, telling docker how to run the containers
* `nginx.conf` - nginx web server configuration file
* `nextcloud-backup-script.sh` - a backup script, to be run daily
You only need to provide the files.</br>
The directories are created by docker compose on the first run.
# docker-compose
Official examples [here](https://github.com/nextcloud/docker/tree/master/.examples/docker-compose)
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`
```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`
```bash
# 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](https://raw.githubusercontent.com/DoTheEvo/selfhosted-apps-docker/master/nextcloud/nginx.conf)<br>
This is nginx web server configuration file, specifically setup
to support fastCGI PHP-FPM.<br>
From [this official nextcloud example
setup](https://github.com/nextcloud/docker/tree/master/.examples/docker-compose/insecure/mariadb/fpm/web)
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**.</br>
Which is named in the `.env` file.</br>
If one does not exist yet: `docker network create caddy_net`
# Reverse proxy
[Nextcloud official documentation](https://docs.nextcloud.com/server/latest/admin_manual/configuration_server/reverse_proxy_configuration.html)
regarding reverse proxy.
Caddy v2 is used, details
[here](https://github.com/DoTheEvo/selfhosted-apps-docker/tree/master/caddy_v2).</br>
There are few extra directives here to fix some nextcloud warnings.
`Caddyfile`
```php
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.</br>
If database env variables were not used then also the database info
would be required here.
![first-run-pic](https://i.imgur.com/lv1x9GF.png)
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.</br>
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*</br>
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](https://github.com/DoTheEvo/selfhosted-apps-docker/tree/a86c8498dc8ebc59546660701a54b839bf417516/nextcloud#security--setup-warnings)
is a link to an older commit that talks in more detail on possible stuff here.<br>
But fuck writing on that noise when nextcloud is now doing phone number area
code notification there.
![status-pic](https://i.imgur.com/0nltwrn.png)
# Troubleshooting
* moving between docker hosts, might need to take ownership of directories<br>
exec in to `nextcloud-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`</br>
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*</br>
- background jobs should be set to Cron</br>
- the last job info should never be older than 10 minutes</br>
# Update
Manual image update:
- `docker-compose pull`</br>
- `docker-compose up -d`</br>
- `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](https://github.com/DoTheEvo/selfhosted-apps-docker/tree/master/kopia_backup)
or [borg](https://github.com/DoTheEvo/selfhosted-apps-docker/tree/master/borg_backup)
to make daily snapshot of the entire docker directory.
#### Restore
* down the containers `docker-compose down`</br>
* delete/move/rename the entire project directory</br>
* from the backups copy back the entire project directory</br>
* start the containers `docker-compose up -d`
# Backup of just user data
User's data daily export going by the
[official procedure.](https://docs.nextcloud.com/server/latest/admin_manual/maintenance/backup.html)</br>
For nextcloud it means entering the maintenance mode, doing a database dump
and backing up several directories containing data, configs, themes.</br>
Daily kopia/borg backup run takes care of backing up the directories.
So only database dump is needed and done with the script.</br>
#### Create a backup script
Placed inside `nextcloud` directory on the host.
`nextcloud-backup-script.sh`
```bash
#!/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`</br>
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 root
* `crontab -e` - add new cron job</br>
* `0 23 * * * /home/bastard/docker/nextcloud/nextcloud-backup-script.sh`</br>
runs it every day [at 23:00](https://crontab.guru/#0_23_*_*_*)
* `crontab -l` - list cronjobs to check
# Restore the user data
[The official docs.](https://docs.nextcloud.com/server/latest/admin_manual/maintenance/restore.html)
Assuming clean start.
* start the containers: `docker-compose up -d`</br>
let them run so they create the file structure
* down the containers: `docker-compose down`
* delete the directories `config`, `data`, `themes` in the freshly created
`nextcloud/nextcloud_data/`
* from the backup of `/nextcloud/nextcloud_data/`, copy the directories
`configs`, `data`, `themes` in to the new `/nextcloud/nextcloud_data/`
* from the backup of `/nextcloud/nextcloud_data_db/`, copy the backup database
named `BACKUP.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:</br>
`docker exec --workdir /var/www/html nextcloud-app chown -R www-data:www-data config data themes`
* restore the database</br>
`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:</br>
`docker container exec --user www-data --workdir /var/www/html nextcloud-app php occ maintenance:mode --off`
* update the systems data-fingerprint:</br>
`docker exec --user www-data --workdir /var/www/html nextcloud-app php occ maintenance:data-fingerprint`
* restart the containers: `docker-compose restart`
* log in