Logo

Braindead.bzh

Game Dev Hobbyist

A blog about my game dev hobby and various stuff.

Menu
Logo

Braindead.bzh

Game Dev Hobbyist

A blog about my game dev hobby and various stuff.

NextCloud + Collabora + DrawIO with Docker Compose on a server with a NAS

In this article I explain how I installed a NextCloud instance with the Collabora and DrawIO integrations using Docker Compose.

Introduction

The task might seem daunting at first, but thanks to Docker and Docker Compose it is actually quite easy, once familiar with the Docker Compose YML language. This article suppose you have knowledge of Linux server administration and how to operate Docker and Docker Compose.

The hardware stack is comprise of a server with a small SSD drive and a high capacity NAS with redundancy (RAID 1), hourly snapshots and daily backups. The software stack is comprise of a PostgreSQL database, Nginx as proxy, NextCloud server, Collabora server and DrawIO server.

System configuration

The software requirements for the server are simple: a Linux OS with Docker and Docker Compose installed. The server should be exposed to the internet, the DNS zone for your domain should point to the server's IP address for <nextcloud.domain.tld>, <collabora.domain.tld> and <drawio.domain.tld>. If you have a firewall, port 80 and 443 have to be opened. The NAS does not need to be accessible from internet, it is even better if it is not, only from the server.

The hardware requirements varies a lot depending on many factors. All I can say is that such an installation with one server and one NAS will probably serve a maximum of a few dozens people.

The docker-compose.yml file

This instruction is based on the example you can find on the official NextCloud docker Github repository (https://github.com/nextcloud/docker/tree/master/.examples/docker-compose/with-nginx-proxy/postgres/fpm). The first step is then to download or clone this repository and go in the folder .examples/docker-compose/with-nginx-proxy/postgres/fpm. The second step is to open docker-compose.yml:

version: '3'

services:
  db:
    image: postgres:alpine
    restart: always
    volumes:
      - db:/var/lib/postgresql/data
    env_file:
      - db.env

  pgbackups:
    image: prodrigestivill/postgres-backup-local
    restart: always
    volumes:
      - backups:/backups
    links:
      - db
    depends_on:
      - db
    env_file:
      - db.env
     
  app:
    image: nextcloud:fpm-alpine
    restart: always
    volumes:
      - nextcloud:/var/www/html
    env_file:
      - db.env
    depends_on:
      - db

  web:
    build: ./web
    restart: always
    volumes:
      - nextcloud:/var/www/html:ro
    environment:
      - VIRTUAL_HOST=<nextcloud.domain.tld>
      - LETSENCRYPT_HOST=<nextcloud.domain.tld>
      - LETSENCRYPT_EMAIL=<admin@domain.tld>
    depends_on:
      - app
    networks:
      - proxy-tier
      - default

  proxy:
    build: ./proxy
    restart: always
    ports:
      - 80:80
      - 443:443
    labels:
      com.github.jrcs.letsencrypt_nginx_proxy_companion.nginx_proxy: "true"
    volumes:
      - certs:/etc/nginx/certs:ro
      - vhost.d:/etc/nginx/vhost.d
      - html:/usr/share/nginx/html
      - /var/run/docker.sock:/tmp/docker.sock:ro
    networks:
      - proxy-tier

  letsencrypt-companion:
    image: jrcs/letsencrypt-nginx-proxy-companion
    restart: always
    volumes:
      - certs:/etc/nginx/certs
      - vhost.d:/etc/nginx/vhost.d
      - html:/usr/share/nginx/html
      - /var/run/docker.sock:/var/run/docker.sock:ro
    networks:
      - proxy-tier
    depends_on:
      - proxy

  collabora:
    image: collabora/code
    container_name: collabora
    restart: always
    expose:
      - 9980
    cap_add:
      - MKNOD
    environment:
      - domain=<nextcloud.domain.tld>
      - VIRTUAL_HOST=<collabora.domain.tld>
      - VIRTUAL_NETWORK=nginx-proxy
      - VIRTUAL_PORT=9980
      - VIRTUAL_PROTO=https
      - LETSENCRYPT_HOST=<collabora.domain.tld>
      - LETSENCRYPT_EMAIL=<admin@domain.tld>
    networks:
      - proxy-tier

  image-export:
    image: jgraph/export-server
    container_name: nextcloud-drawio-export
    expose:
      - "8000"
    networks:
      - proxy-tier
    volumes:
      - fonts:/usr/share/fonts/drawio 
    restart: always
  
  drawio:
    image: jgraph/drawio
    container_name: nextcloud-drawio
    expose:
      - 8080
    networks:
      - proxy-tier
    depends_on:
      - image-export
    environment:
      - VIRTUAL_HOST=<drawio.domain.tld>
      - VIRTUAL_PORT=8080
      - VIRTUAL_NETWORK=nginx-proxy
      - LETSENCRYPT_HOST=<drawio.domain.tld>
      - LETSENCRYPT_EMAIL=<admin@domain.tld>
      - EXPORT_URL=http://image-export:8000/
    restart: always

volumes:
  db:
  nextcloud:
    driver_opts:
      type: 'nfs'
      o: 'addr=<NAS IP address>,nolock,soft,rw'
      device: ':/path/to/nextcloud/folder'
  certs:
  vhost.d:
  html:
  backups:
    driver_opts:
      type: 'nfs'
      o: 'addr=<NAS IP address>,nolock,soft,rw'
      device: ':/path/to/database/backup/folder'
  fonts:
    driver_opts:
      type: 'nfs'
      o: 'addr=<NAS IP address>,nolock,soft,rw'
      device: ':/path/to/fonts/folder'

networks:
  proxy-tier:

The services

  • db: this is the PostgreSQL database instance.
  • pgbackups: this service will automatically backup the database on a daily schedule.
  • app: this is the NextCloud application service.
  • web: this an Nginx instance which serve the NextCloud application to the proxy.
  • proxy: this an Nginx proxy which serve all our applications, NextCloud, Collabora and DrawIO, to the internet.
  • letsencrypt-companion: this is a service that automatically generate Letsencrypt SSL certifcates for our applications.
  • collabora: this is the Collabora application service.
  • image-export: this is the export server for DrawIO.
  • drawio: this is the DrawIO application service.

The volumes

  • db: this is the database storage, this volume is a default volume as I want my database to run on the SSD.
  • nextcloud: this is the storage for all the files and data of NextCloud, this include installed apps and users' data, this is why it is setup to use the NAS.
  • certs, vhost.d, html: this volumes help to share the necessary data between the Nginx proxy and the Letsencrypt Companion for them to work properly.
  • backups: this is the storage for the database backups and therefore it is using the NAS.
  • fonts: this is the storage for the DrawIO fonts, it is probably not necessary to have it on the NAS, but if you don't want to loose custom fonts used in your diagrams it is the best choice.

The db.env file

You light have seen db.env referenced multiple times in the YML. This file is convenient way to have all the database parameters in one location instead of duplicating the same information for each services requiring access to it. Open db.env.

POSTGRES_PASSWORD=<strong password>
POSTGRES_DB=<database name>
POSTGRES_USER=<database user>
POSTGRES_HOST=db
POSTGRES_EXTRA_OPTS=-Z9 --schema=public --blobs
SCHEDULE=@daily
BACKUP_KEEP_DAYS=7
BACKUP_KEEP_WEEKS=4
BACKUP_KEEP_MONTHS=6
HEALTHCHECK_PORT=80

It is a pretty straightforward file with multiple pairs of environment variable and their respective value. As you can see it also contains the backup configuration.

Integration

Once your NextCloud setup and ready, you can install the Collabora Online and Draw.io App integration from the admin account. In the settings the URL for the Collabora Server will be https://<collobora.domain.tld> and the Draw.io URL will be https://<drawio.domain.tld>.

Conclusion

In this times of uncertainty, it is probably a good idea to reduce your dependency to the GAFAM and NextCloud is the best solution around for that. NextCloud can be hosted in a data-center near you, on premise or even on a Raspberry Pi for your home usage. NextCloud is accessible through the Web or using the App for Windows, Mac, Linux, Android or iOS.

I also strongly suggest you to install NextCloud Talk which integrates perfectly into NextCloud and provides fully-encrypted chat, audio and video call. It also comes with an App for Android and iOS.

Written by Olivier on Sunday April 5, 2020

« Lithium powered waterproof RGB LED lights Godot Quick Tip #4 - Conditional function execution using ConfirmationDialog and yield »