After struggling a bit to get this set-up myself, I figured I would make a post to document the process, for myself, and in case anyone else is having the same struggle, to get NexCloud to run in docker container, using a reverse proxy (also in a container), connecting to a postgresql database on the host machine (not in a container), and lets throw in letsencrypt certs for good measure. Wow, that was mouthful.

The first thing we want to do is set-up a bridged network connection for docker to use to connect back to the host system, so that it can connect to postgres. Here I am using 172.30.0.0/24 but you could use any private network address space.

docker network create -d bridge --subnet 172.30.0.0/24 --gateway 172.30.0.1 dockernet

Next lets set up the docker-compose.yml file.

version '2'

services:
  rproxy:
    image: jwilder/nginx-proxy
    container_name: rproxy
    ports:
      - "80:80"
      - "443:443"
    restart: always
    environment:
      - ENABLE_IPV6=false
    volumes:
      - /var/run/docker.sock:/tmp/docker.sock:ro
      - /opt/letsencrypt:/etc/nginx/certs
      - /opt/nginx/max.conf:/etc/nginx/conf.d/max.conf:ro
 
  nextcloud:
     image: nextcloud
     container_name: nextcloud
     expose:
       - "443"
     environment:
       - VIRTUAL_HOST=mynextcloud.example.com 
     extra_hosts:
       database: 172.30.0.1
     volumes:
       - /opt/nextcloud:/var/www/html
     restart: always

First lets talk about the reverse proxy. I am using the jwilder/nginx-proxy container for my reverse proxy. The import parts here are the volumes. The first volume is a socket file required by the proxy. The second volume is the location of the public and private SSL certs.

The way the reverse proxy works is you need to have the certs in the specified directory and be named with your hostname (as declared by your VIRTUAL_HOST environment variable under the nextcloud section) with .crt for the public key and .key for the private key. So for the example above it would be mynextcloud.example.com.crt and mynextcloud.example.com.key, both of wich would need be located in /opt/letsencrypt.  

I used standalone and certonly options with certbot to genrate certificates. This presents a few minor challenges when renewing your certs (which expire every 3 months). First you need to stop your docker containers. Second you will have to manually move and rename the certs (which I know isn't ideal), and then restart docker. However, there are ways to automate this. Cert-bot has renewal-hooks (/etc/letsencrytp/renewal-hooks), which allow you to run scripts prior to and after the renew command excutes. So it isn't too dificult to automate the process, my setup goes like this.

Pre Hooks:

  • stop docker-compose

Post Hooks:

  • Look for new cert files in /etc/letsencrypt/archive
  • Copy and rename any new cert files
  • Start docker-compse back up

The last volume setting sets the max upload size of files we can upload to NextCloud. Since NextCloud is designed for storing files want to configure nginx to allow larger uploads than 1 Mib, which is the default in nginx. The only thing we need in this file is to set the client_max_body_size setting. Below I am setting it to 10Gb.

client_max_body_size 10000m;

Now on to the NextCloud section. In the enviorment specify the domain name as VIRTUAL_HOST, this is how the proxy will know where to direct traffic.

Under extra_hosts is where we specify the IP that links back to our host system (as we setup first with the docker network create command). We are giving this a simple name of database.

The volume for NextCloud is extremley important, this is what will allow your nextcloud settings to presist, otherwise you will lose all your settings every time docker goes down and then comes back up. In my example I made a directroy on the host machine /opt/nextcloud and am mapping it to /var/www/html in the container. I learned the hard way that you need to map the entire /var/www/html directory and not just /var/www/html/data.

That is it, now time to fire it up.

Be sure to click the storage & database arrow to expand the options (otherwise it default to SQLite).

Be sure to leave the Data folder as the default (/var/www/html/data).

Select PosgreSQL, and enter your database username, password, the name of the database, and then (this is the important part) just put the world database in for server location/address.  This is telling NextCloud to reffrence extra_hosts, then the database item we set in the docker-compose file.