Wiki/Guides/Docker/04Nextcloud.md
2025-04-10 04:10:54 +02:00

8.9 KiB

title, description, published, date, tags, editor, dateCreated
title description published date tags editor dateCreated
04 Nextcloud true 2023-05-03T02:50:12.377Z markdown 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