336 lines
8.9 KiB
Markdown
336 lines
8.9 KiB
Markdown
---
|
|
title: 04 Nextcloud
|
|
description:
|
|
published: true
|
|
date: 2023-05-03T02:50:12.377Z
|
|
tags:
|
|
editor: markdown
|
|
dateCreated: 2023-05-03T01:58:56.581Z
|
|
---
|
|
|
|
|
|
# Nextcloud
|
|
Nextcloud is a great application, It is great for storing and syncing data, storing your contacts, bookmarks, passwords, calendar, tasks. It also has a great RSS reader, full office suite and many many more. I truly can't live without it. And neither should you which is why I picked it as the example for this guide
|
|
|
|
First we need to create a network for the service.
|
|
|
|
sudo docker network create --subnet=172.20.30.0/24 nextcloud
|
|
|
|
Next we are going to create some folders
|
|
|
|
mkdir -p ~/docker/nextcloud
|
|
|
|
Now we will create a docker compose file
|
|
|
|
vim ~/docker/nextcloud/docker-compose.yml
|
|
|
|
Add in the following text
|
|
|
|
```
|
|
version: '3'
|
|
|
|
services:
|
|
nextcloud:
|
|
image: nextcloud
|
|
container_name: nextcloud
|
|
restart: always
|
|
volumes:
|
|
- /etc/localtime:/etc/localtime:ro
|
|
- /data/nextcloud:/var/www/html
|
|
networks:
|
|
nextcloud:
|
|
ipv4_address: 172.20.30.10
|
|
|
|
networks:
|
|
nextcloud:
|
|
external: true
|
|
name: nextcloud
|
|
ipam:
|
|
config:
|
|
- subnet: 172.20.30.0/24
|
|
```
|
|
|
|
Now we need to add a server block for nextcloud to the Nginx config file so create a file that will be included by the main nginx config file
|
|
|
|
sudo vim /data/nginx/config/services/nextcloud.active
|
|
|
|
add in the following text
|
|
|
|
```
|
|
server {
|
|
server_name example.com;
|
|
listen 443 ssl;
|
|
|
|
# Settings
|
|
autoindex off;
|
|
client_max_body_size 5000M;
|
|
|
|
# Locations
|
|
location / {
|
|
proxy_pass http://nextcloud:80;
|
|
proxy_http_version 1.1;
|
|
proxy_cache_bypass $http_upgrade;
|
|
proxy_ssl_server_name on;
|
|
proxy_set_header Upgrade $http_upgrade;
|
|
proxy_set_header X-Real-IP $remote_addr;
|
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
proxy_set_header X-Forwarded-Proto $scheme;
|
|
proxy_set_header X-Forwarded-Host $host;
|
|
proxy_set_header X-Forwarded-Port $server_port;
|
|
proxy_set_header Connection "upgrade";
|
|
proxy_set_header Host $host;
|
|
proxy_connect_timeout 600m;
|
|
proxy_send_timeout 600m;
|
|
proxy_read_timeout 600m;
|
|
}
|
|
|
|
location /.well-known/carddav {
|
|
return 301 $scheme://$host/remote.php/dav;
|
|
}
|
|
|
|
location /.well-known/caldav {
|
|
return 301 $scheme://$host/remote.php/dav;
|
|
}
|
|
|
|
location ~ /\.(?!well-known) {
|
|
deny all;
|
|
}
|
|
|
|
location = /favicon.ico {
|
|
log_not_found off;
|
|
}
|
|
|
|
location = /robots.txt {
|
|
log_not_found off;
|
|
}
|
|
|
|
# GZip
|
|
gzip on;
|
|
gzip_vary on;
|
|
gzip_proxied any;
|
|
gzip_comp_level 6;
|
|
gzip_types text/plain text/css text/xml application/json application/javascript application/rss+xml application/atom+xml image/svg+xml;
|
|
|
|
# Headers
|
|
add_header X-XSS-Protection "1; mode=block" always;
|
|
add_header X-Content-Type-Options "nosniff" always;
|
|
add_header X-Frame-Options "SAMEORIGIN";
|
|
add_header Referrer-Policy "no-referrer-when-downgrade" always;
|
|
add_header Content-Security-Policy "default-src 'self' http: https: ws: wss: data: blob: 'unsafe-inline'; frame-ancestors 'self';" always;
|
|
add_header Permissions-Policy "interest-cohort=()" always;
|
|
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
|
|
|
|
# SSL
|
|
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
|
|
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
|
|
ssl_trusted_certificate /etc/letsencrypt/live/example.com/chain.pem;
|
|
}
|
|
|
|
# Redirect
|
|
server {
|
|
listen 80;
|
|
server_name example.com;
|
|
return 301 https://example.com$request_uri;
|
|
}
|
|
```
|
|
|
|
Be sure to replace `example.com` 6 times
|
|
|
|
Now we need to add nextcloud to the mariadb and nginx networks, because it needs a database and a proxy.
|
|
|
|
open the nginx compose file
|
|
|
|
vim ~/docker/nginx/docker-compose.yml
|
|
|
|
add the nextcloud network so it looks like this
|
|
|
|
```
|
|
version: '3'
|
|
|
|
services:
|
|
nginx:
|
|
image: nginx:latest
|
|
container_name: nginx
|
|
restart: always
|
|
volumes:
|
|
- /data/nginx/config:/etc/nginx
|
|
- /data/nginx/log/error.log:/var/log/error.log
|
|
- /data/nginx/log/access.log:/var/log/access.log
|
|
- /etc/letsencrypt/:/etc/letsencrypt/
|
|
- /etc/localtime:/etc/localtime:ro
|
|
ports:
|
|
- 80:80
|
|
- 443:443
|
|
- 8448:8448
|
|
networks:
|
|
nextcloud:
|
|
ipv4_address: 172.20.30.20
|
|
|
|
networks:
|
|
nextcloud:
|
|
external: true
|
|
name: nextcloud
|
|
```
|
|
|
|
open the mariadb compose file
|
|
|
|
vim ~/docker/mariadb/docker-compose.yml
|
|
|
|
add the nextcloud network so it looks like this
|
|
|
|
```
|
|
version: '3'
|
|
|
|
services:
|
|
mariadb:
|
|
image: mariadb:latest
|
|
container_name: mariadb
|
|
restart: always
|
|
command: --transaction-isolation=READ-COMMITTED --binlog-format=ROW --skip-innodb-read-only-compressed
|
|
volumes:
|
|
- /data/mariadb/data:/var/lib/mysql
|
|
- /data/mariadb/config:/etc/mysql/conf.d
|
|
- /data/mariadb/logs:/var/log/mysql
|
|
- /etc/localtime:/etc/localtime:ro
|
|
|
|
environment:
|
|
- MYSQL_ROOT_PASSWORD=YOURMYSQLROOTPASSWORD
|
|
networks:
|
|
nextcloud:
|
|
ipv4_address: 172.20.30.30
|
|
|
|
networks:
|
|
nextcloud:
|
|
external: true
|
|
name: nextcloud
|
|
```
|
|
|
|
Now we are going to start the nextcloud container and restart the nginx and mariadb containers.
|
|
|
|
sudo docker-compose -f ~/docker/nextcloud/docker-compose.yml up -d
|
|
sudo docker-compose -f ~/docker/nginx/docker-compose.yml down && sudo docker-compose -f ~/docker/nginx/docker-compose.yml up -d
|
|
sudo docker-compose -f ~/docker/mariadb/docker-compose.yml down && sudo docker-compose -f ~/docker/mariadb/docker-compose.yml up -d
|
|
|
|
Nextcloud should be accessable from your browser using the domain you chose, But first we need to create a database, user and set the permissions.
|
|
|
|
You can get into the database with the following command (only if mariadb is running)
|
|
|
|
sudo docker exec -it mariadb mysql -p
|
|
|
|
Enter the Mysql root password you provided during the creation of the mariadb container and you should be in.
|
|
|
|
Now run the following commands to create a database, create a user with privileges, and make them take effect.
|
|
|
|
create database nextcloud;
|
|
create user nextcloud@'172.20.30.10' identified by 'NEXTCLOUDDATABASEPASSWORD';
|
|
grant all privileges on nextcloud.* to nextcloud@'172.20.30.10';
|
|
flush privileges;
|
|
|
|
You can exit the mysql prompt with `exit;` and then pressing enter.
|
|
|
|
Now we just need to go to example.com and follow the steps
|
|
|
|
The Database is nextcloud, the user is nextcloud, The IP is 172.30.0.30:3306 and the password is what you gave it.
|
|
|
|
We also need to force HTTPS, else it will give problems since we are running from behind a proxy
|
|
|
|
sudo vim /data/nextcloud/config/config.php
|
|
|
|
Add in the following line preferrrably under the overwrite.cli.url line.
|
|
|
|
```
|
|
'overwriteprotocol' => 'https',
|
|
```
|
|
|
|
Nextcloud requires some tasks to be executed every 5 minutes, for that we are going to use systemd timers, like we did for certbot
|
|
|
|
Create a little script
|
|
|
|
vim ~/scripts/nextcloudcron.sh
|
|
|
|
add in the following content
|
|
|
|
```
|
|
#!/bin/bash
|
|
|
|
docker exec -u 33 -t nextcloud php -f /var/www/html/cron.php
|
|
exit
|
|
```
|
|
|
|
Create a systemd service
|
|
|
|
sudo vim /etc/systemd/system/nextcloudcron.service
|
|
|
|
Add in the following content
|
|
|
|
```
|
|
[Unit]
|
|
Description=Runs Nextcloud Cron
|
|
Wants=nextcloudcron.timer
|
|
|
|
[Service]
|
|
Type=oneshot
|
|
ExecStart=/bin/bash /home/USERNAME/scripts/nextcloudcron.sh
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
```
|
|
|
|
Create a timer file
|
|
|
|
sudo vim /etc/systemd/system/nextcloudcron.timer
|
|
|
|
and add in the following content
|
|
|
|
```
|
|
[Unit]
|
|
Description=Runs Nextcloud Cron
|
|
Requires=nextcloudcron.service
|
|
|
|
[Timer]
|
|
Unit=cron5.service
|
|
OnBootSec=5min
|
|
OnUnitActiveSec=5min
|
|
|
|
[Install]
|
|
WantedBy=timers.target
|
|
```
|
|
|
|
Finally start the timer
|
|
|
|
sudo systemctl enable --now nextcloudcron.timer
|
|
|
|
Nextcloud should be all good and ready to go, You can check the persistance by completely deleting all containers and all volumes, When you start it again all your stuff should still be there :)
|
|
|
|
Nextcloud has its own Brute force protection, but we still are going to add a fail2ban filter because we want attackers to be banned from all services and not just nextcloud.
|
|
|
|
So lets create a new nextcloud filter
|
|
|
|
sudo vim /etc/fail2ban/filters.local
|
|
|
|
add in the following content
|
|
|
|
```
|
|
[Definition]
|
|
failregex=^{"reqId":".*","remoteAddr":".*","app":"core","message":"Login failed: '.*' \(Remote IP: '<HOST>'\)","level":2,"time":".*"}$
|
|
^{"reqId":".*","level":2,"time":".*","remoteAddr":".*","user":".*","app":".*","method":".*","url":".*","message":"Login failed: '.*' \(Remote IP: '<HOST>'\)".*}$
|
|
^{"reqId":".*","level":2,"time":".*","remoteAddr":".*","user":".*","app":".*","method":".*","url":".*","message":"Login failed: .* \(Remote IP: <HOST>\).*}$
|
|
```
|
|
|
|
Now add the filter to your main fail2ban config file
|
|
|
|
sudo vim /etc/fail2ban/jail.local
|
|
|
|
Add the following to the end of the file
|
|
|
|
```
|
|
## Nextcloud
|
|
[nextcloud]
|
|
filter = nextcloud
|
|
enabled = true
|
|
logpath = /data/nextcloud/data/nextcloud.log
|
|
```
|
|
|
|
restart fail2ban to make it take effect
|
|
|
|
sudo systemctl restart fail2ban |