How to install NextCloud using Docker Compose: a comprehensive guide

; Date: Wed Dec 13 2023

Tags: Docker »»»» NextCloud »»»» Self Hosting

NextCloud is open source software implementing the equivalent to Google Drive, Dropbox, and the like. Beyond file sharing, it supports document editing, calendars, email, and is attempting to compete with the full breadth of Google Workspace services. It can be self-hosted on your own server, giving you privacy you don't get from commercial cloud services.

NextCloud is an example of the open source community implementing the equivalent of services from a massive tech company. In this case, Google Workspace is a very popular service used by individuals, offering file storage, document editing, email, calendars, and more. But, what about the worries over what Google is doing with all the data we give it?

With NextCloud you gain control over your data, so long as you can handle hosting the software.

There are several models for hosting NextCloud.

  • Native installation on Linux -- It is supported on a variety of Linux systems, and requires MySQL 8.0 and PHP 8.x. Simply download and run an installer package on a web host.
  • Linux package managers -- NextCloud is available as a "Snap Package" for Ubuntu.
  • Virtual Machines on VirtualBox etc -- The NextCloud VM project contains scripts for this purpose.
  • Raspbian on Raspberry Pi -- The NextCloudPI scripts focus on that hardware.
  • Docker -- Several Docker images for NextCloud are available, but are not officially supported by NextCloud.

In this article we'll discuss the Docker installation for NextCloud. In my eye Docker is preferred for these reasons:

  • It is generally safer and easier than native to the host system.
  • Docker containers encapsulate everything required to run the service, easing setup.
  • If a miscreant breaks through application-level security, containerization limits damage to the running container, which is easily recreated and restarted.

The (hub.docker.com) unofficial Docker image for NextCloud is maintained by the Docker community. By contrast, NextCloud AIO, a.k.a. All In One, is maintained by NextCloud Gmbh, and contains a number of built-in features and back-end services for a complete NextCloud experience.

In this article we learn how to do a complete NextCloud installation, using the unofficial Docker image, that is ready for production use, and solves several common problems. This includes a MariaDB instance for the database, a REDIS instance for performance improvements, resolving several common issues (timeouts and the like), and correctly configuring the NextCloud Docker container.

The README for that container gives sample Docker Compose files. Since those Compose files have several problems, we show a more complete Compose file for NextCloud that works much better. We also discuss configuration of an NGINX proxy for NextCloud using NGINX Proxy Manger.

Setting up Docker

To run NextCloud under Docker, your system must have the Docker platform installed. The Docker platform - either Docker Desktop or Docker Engine - is required for executing Docker containers.

As we'll see in a minute, with a Docker Compose file we can describe in a relatively small file the deployment of several services required to run NextCloud. This is a huge advantage Docker gives us over deploying software services on the native operating system.

Installing Docker is beyond the scope of this article. In a separate article, I discuss Docker setup on macOS, Windows or Linux: Installing Docker Engine or Desktop on Ubuntu, macOS or Windows

You must decide where you will install NextCloud. You might run it on your laptop to have access to distributed services on several locations. But, typically it is installed on a server which you can access from multiple computers.

On your laptop you're likely to install Docker Desktop, while on that server you're likely to install Docker Engine.

Setting up the Docker hosting environment

Beyond having Docker installed it's useful to follow an organized file-system hierarchy for deploying multiple Docker-based services. It's unlikely you'll only host NextCloud, because there are many other services of interest.

It is best that each service be managed in its own directory, and that all Docker-hosted services are sitting next to each other in the file system.

Hence, create a directory - /path/to/docker - on your computer. Then, create one child directory for each service.

# Do this once
$ mkdir -p /path/to/docker
# Do this for each service
$ mkdir -p /path/to/docker/SERVICE-NAME

Therefore you know that for any Docker-related task, you navigate to /path/to/docker as the first step.

For NextCloud, you run this command:

$ mkdir -p /path/to/docker/nextcloud

Some common examples for /path/to/docker are /home/USER-NAME/docker, /opt, /opt/docker, or even just /docker.

You're unlikely to only install NextCloud, since there are many useful applications available as Docker images. It is best for all such applications to be installed next to each other. There are two best practices to consider:

  • All applications installed with Docker are stored in /path/to/docker sitting next to each other in the filesystem. For example, /path/to/docker/nextcloud, /path/to/docker/gitea, /path/to/docker/jenkins, etc.
  • All files related to hosting a Docker image should reside within the /path/to/nextcloud/APP directory.

Another good practice is to use a Docker administration tool. Portainer is very popular, especially for larger organizations. DockGe is a new application which is worth a look.

Basic Docker Compose file for NextCloud

Let's start this with a simple docker-compose.yml for NextCloud derived from what's shown in the README for the container.

version: '3.8'

# volumes:
#   nextcloud:
#   db:

services:
  nextcloud_db:
    # This could be a specific version like mariadb:10.6
    image: mariadb
    restart: always
    command: --transaction-isolation=READ-COMMITTED --binlog-format=ROW
    networks:
      - cloudnet
    volumes:
      # - db:/var/lib/mysql
      - /opt/nextcloud/db:/var/lib/mysql
    environment:
      - MYSQL_RANDOM_ROOT_PASSWORD=true
      - MYSQL_PASSWORD=PASSWORD
      - MYSQL_DATABASE=nextcloud
      - MYSQL_USER=nextcloud

  nextcloud:
    # This could be just 'nextcloud' to get the latest version
    image: nextcloud:28-apache
    restart: always
    networks:
      - cloudnet
    # ports:
    #  - 8080:80
    volumes:
      # - nextcloud:/var/www/html
      - /opt/nextcloud/docroot:/var/www/html
    environment:
      - NEXTCLOUD_DATA_DIR=/var/www/html/data
      - MYSQL_PASSWORD=PASSWORD-as-above
      - MYSQL_DATABASE=nextcloud
      - MYSQL_USER=nextcloud
      - MYSQL_HOST=nextcloud_db

networks:
  cloudnet:
    name: cloudnet
    driver: bridge

This contains two services: MariaDB and NextCloud. The configuration for both is fairly straight-forward configurations of each. Let's talk about what's in the file.

The version is set to 3.8 because that's the modern version of Docker Compose.

The NextCloud image selected is nextcloud:28-apache. The part before the : is the image name, in this case just nextcloud. The part after the : is a tag where the name is selected by the image maintainer. For the NextCloud image, the tag name includes a version name as well as an indication of the technology used. In this case, version 28 corresponds to Nextcloud Hub 7 which is a marketing version number. That it mentions apache means it is executing under Apache with PHP support.

The volumes declarations serve to persist the data outside the container. The contents of Docker containers are destroyed when we destroy and recreate the container. In the case of NextCloud, like many services, we need some of the data to be saved (persisted) when that happens.

The effect of a volumes declaration is to map a container pathname to a host pathname, and for a portion of the container filesystem to live on the host. The container can be destroyed and recreated at will without harming the data stored in the host filesystem.

The recommended Compose file uses the volumes declarations which are commented-out here. In such a case, the host directory is in an obtusely-located path within the Docker platform filesystem.

I prefer to explicitly declare the host directory path so that its location is known. The uncommented volumes declarations are how this is done. Going by the best practice named earlier, the whole NextCloud instance is contained within /opt/nextcloud, with the database files stored in /opt/nextcloud/db and the NextCloud files stored in /opt/nextcloud/docroot.

The /opt prefix is chosen because, on the virtual private server (VPS) where I've installed NextCloud, that directory was empty. I've used the /opt directory for storing all Docker-based services installed on that server.

The container README suggests using a links declaration to connect the NextCloud and MariaDB containers. The links setting has been deprecated for years. Instead, the best practice is to set up a bridge network, and connect the containers to that network. That's what is done here, first by declaring cloudnet, then referencing it from both containers.

For a network like cloudnet, Docker ensures each container has a host-name matching the container name. Hence, the MariaDB instance has the hostname nextcloud_db within cloudnet. This is reflected in the MYSQL_HOST setting on the nextcloud container.

Simple Docker deployment of Nextcloud, image by David Herron

This is the NextCloud deployment architecture as described in the Compose file shown earlier.

While it is easy to understand, there's a security issue. The database container should not be publicly reachable. By restructuring the bridge networks, database access can be restricted to the NextCloud container.

Complete Docker subnet setup for NextCloud

My production deployment environment uses NGINX Proxy Manager in front of the several services on the host. The application services (like NextCloud), and N.P.M., are attached to a bridge network. The database containers are kept on a separate bridge network.

More complete Docker deployment of Nextcloud, image by David Herron

The architecture I use in production is more like this.

An option is:

services:
  nextcloud_db:
    ...
    networks:
      - dbnet
    ...

  nextcloud:
    ...
    networks:
      - dbnet
      - cloudnet
    ...

networks:
    servernet:
        external:
            name: cloudnet
    dbnet:
        external:
            name: dbnet

The two networks, cloudnet and dbnet, provide a layer of separation between the database and miscreants who might break in. The purpose of cloudnet is connecting services, like NextCloud, to the NGINX Proxy Manager. The purpose of dbnet is to connect these services with their database server.

Because these are described as external networks, their existence is maintained outside of the Compose file. That means to either use the docker network command, or an administrative GUI like Portainer. My production system has Portainer installed.

Any Compose file using these networks will reference them using an external network declaration as shown here.

Running initial setup for NextCloud

Save the docker-compose.yml into an empty directory, then run the following:

$ docker network create cloudnet
$ docker network create dbnet

This sets up the networks, as just discussed. If you prefer, a Docker administrative GUI like Portainer offers a nicer point-and-click experience.

$ docker compose up -d

Notice, it is docker compose rather than docker-compose. The latter has been deprecated by the Docker team. The features that had been in docker-compose are now incorporated in the main docker command.

The docker compose up command launches the stack described by the Compose file. The -d option says to detach the terminal from the logging output.

To watch the logging output, run docker compose logs -f.

Using the Compose file shown above, NextCloud will be at http://SERVER on port 80. You can connect directly to this port using your web browser. But it's recommended to instead place services behind a proxy manager. That's where NGINX Proxy Manager comes into play.

The ports directive to remap that to another port number, if needed. For example, you can map the service to port 4080 with this:

services:
  ...
  nextcloud:
    ...
    ports:
      - 4080:80
    ...

In this case you would connect your browser to http://SERVER:4080.

Since it's recommended to put services behind a proxy, let's look at what's required for use with NGINX Proxy Manager.

Configuring NextCloud behind NGINX Proxy Manager

NGINX Proxy Manager (N.P.M.) is an excellent tool to place between your users and your service. Proxy servers provide a layer of security because it prevents direct access to the service. N.P.M. simplifies assigning domain names to your services, and provisioning SSL certificates from Lets Encrypt to enable HTTPS protection for your server.

You might do, as I do, host several services on one server. They cannot all be visible on ports 80 and 443. N.P.M. makes it easy to connect each service to a specific domain name. Traffic arrives at N.P.M. for a domain, like cloud.example.com, and the N.P.M. proxy directs that traffic to the nextcloud container.

Installing and configuring N.P.M. is way outside the scope of this article. It's easy to setup if you don't have it running, or else you can skip this section and connect directly to the NextCloud service.

NGINX Proxy Manager config for NextCloud, by David Herron

This is the desired end-goal. NextCloud is available on a domain name of your choosing. The proxy manager routes traffic to the named Docker container. Lets Encrypt is used for SSL.

This starts by defining a domain name. Go to your domain registrar and configure one. The details are dependent on the registrar you use, and many other considerations.

In my case, the VPS where the services are installed have an IP address provided by the web hosting provider. I've configured a domain name like host001.example.com with an A record containing that IP address. Domain names for each service are implemented with a CNAME record, such as cloud.example.com, naming the host, such as host001.example.com.

In the NGINX Proxy Manager dashboard, click on Add Proxy Host, and you'll see a popup window looking like this:

At the top, enter your public domain name, such as cloud.example.com. Below that, leave the scheme as http, enter the name for the docker container, such as nextcloud, and the port number, such as 80. In my case, even though a ports directive was used, N.P.M. was unable to connect to the NextCloud service using the mapped port. Instead, it worked to use the host name nextcloud and port 80. Enable the other settings shown here. Then close this window by clicking the Save button.

A section will appear in the N.P.M. dashboard similar to what's shown above.

Next, we need to provision an SSL certificate. N.P.M. can do this via Lets Encrypt.

On the far right-hand-side of the list of proxy hosts, you'll find a vertical ... button. Clicking on that opens a menu, where one of the choices is Edit. The Edit choice reopens the dialog window. Click on the SSL tab.

Enter your domain name in the box.

A drop-down menu will appear in which you can choose to provision an SSL certificate from Lets Encrype.

Lets Encrypt is a free service for SSL certificates. Normally such certificates are expensive, so Lets Encrypt is performing a valuable public service.

If this is your first time using Lets Encrypt you must register. Simply provide an email address and agree to some terms of services. This can be handled through the N.P.M. user interface.

Click the options shown here. Then click Save.

Once you've done this you should be able to paste https://cloud.example.com into your browser and the NextCloud setup will appear.

Initial configuration of NextCloud

Enter the correct URL in your browser. There will be boxes to enter a user name for the ADMIN user, as well as a password. There may be a checkmark to tell NextCloud to install some recommended applications. In NextCloud-ese, an application is an addon which can be installed to expand the functionality available in your NextCloud instance.

It's recommended to not use admin as the administrator user name, since that's easy to guess.

Click on the Install button, and be prepared to wait for awhile.

My experience was that this step timed out in the browser. I simply reloaded the browser window, and found NextCloud ready to be used. I've looked for solutions and found no recommendations which helped.

During the setup phase, you gave a user name and password for the ADMIN user. Login using that combination, and you'll be in NextCloud. From there, you can explore the features, change some settings, install NextCloud applications, and so forth. What you do with it is up to you, and what we're focused on here is setup of NextCloud.

Handling Setup and Security Warnings

A very important check to make is in the Settings area. In the upper-right corner click on the button, like so:

There are many useful choices here, and for now we are interested in Settings. On the current NextCloud version, the Settings choice may be split into Personal Settings and Administration Settings. If so, choose the latter.

In the Settings area, there is a list of tabs in a column on the left-hand side. Scroll down to the Administration section, and click on the Overview choice. This page gives an overview of your NextCloud instance.

On this page, there is some JavaScript code which will execute to check for common issues. It should show something like this:

There are several issues shown on this page which turned up as I fixed issues. Lets see how to fix issues in NextCloud. It's important to notice that every message is marked with a severity rating, and includes a link to documentation discussing the issue.

In the following sections we discuss solutions for these issues:

  • The "Strict-Transport-Security" HTTP header is not set to at least "15552000" seconds. For enhanced security, it is recommended to enable HSTS as described in the security tips.
  • Your web server is not properly set up to resolve "/.well-known/caldav". Further information can be found in the documentation.
  • Your web server is not properly set up to resolve "/.well-known/carddav". Further information can be found in the documentation.
  • Last background job execution ran 2 hours ago. Something seems wrong. Check the background job settings.
  • You are accessing your instance over a secure connection, however your instance is generating insecure URLs. This most likely means that you are behind a reverse proxy and the overwrite config variables are not set correctly. Please read the documentation page about this
  • Your remote address was identified as "10.0.0.2" and is bruteforce throttled at the moment slowing down the performance of various requests. If the remote address is not your address this can be an indication that a proxy is not configured correctly. Further information can be found in the documentation
  • Your installation has no default phone region set. This is required to validate phone numbers in the profile settings without a country code. To allow numbers without a country code, please add "default_phone_region" with the respective ISO 3166-1 code of the region to your config file.
  • The database is used for transactional file locking. To enhance performance, please configure memcache, if available. See the documentation for more information.
  • The reverse proxy header configuration is incorrect, or you are accessing Nextcloud from a trusted proxy. If not, this is a security issue and can allow an attacker to spoof their IP address as visible to the Nextcloud. Further information can be found in the documentation
  • You have not set or verified your email server configuration, yet. Please head over to the Basic settings in order to set them. Afterwards, use the "Send email" button below the form to verify your settings.
  • Server has no maintenance window start time configured. This means resource intensive daily background jobs will also be executed during your main usage time. We recommend to set it to a time of low usage, so users are less impacted by the load caused from these heavy tasks.
  • The database is missing some indexes. Due to the fact that adding indexes on big tables could take some time they were not added automatically. By running "occ db:add-missing-indices" those missing indexes could be added manually while the instance keeps running. Once the indexes are added queries to those tables are usually much faster. Missing optional index "mail_messages_msgid_idx" in table "mail_messages".

The following sections discuss the solutions for these problems.

Fixing the Strict-Transport-Security warning

This is easy to fix. Look at the N.P.M. setup recommended earlier and you see HSTS was not checked. To fix this, open the configuration dialog, navigate to the SSL tab, and click the HSTS button, then click Save. After reloading the settings overview page, this message should go away.

Fixing the Last background job execution ran 2 hours ago error

As with many frameworks, there are background tasks which must execute every so often. In this case, click on the URL to documentation and you see three choices to handle background task execution. These choices are:

  • AJAX - Which executes tasks when pages are loaded.
  • Webcron - This is a kind of web service which is a "hosted cron". This means an external service will be configured in a cron-like way to make a request on cron.php.
  • System Cron - Instead of using an external Cron service, use one on the host system.

On Unix/Linux-like operating sytems, Cron is a background process for scheduling tasks. The classical example is running a shell script at 3AM to run a backup procedure.

Unfortunately the NextCloud Docker container does not have a Cron running. However, I have developed a suitable Cron container. Using it simply requires deploying the container on the Docker infrastructure, then dropping a shell script into a directory.

It's possible to use the Cron service on the Docker host system.

An external Webcron service is a simple option. There are many 3rd party services where you can schedule tasks via a web GUI. You would use one if you're unwilling to host another Docker container. Alternatively, you can use Cron on the host where your Docker instance is runnign.

But, let's discuss setting up a Crond container to your local Docker instance. The advantage of (hub.docker.com) robogeek/crond is that it's extremely light-weight (built on Alpine Linux), and is easy to configure. I've written a blog post about it at Scheduling background tasks using cron in a Docker container.

Each service uses a directory /opt/SERVICE-NAME to hold files related to that service. Again, this is the best practice named earlier. For Crond, a directory named scripts is created in this directory. Hence, the setup of a script to trigger the NextCloud cron.php looks like this:

$ mkdir /opt/nextcloud/scripts

$ cat /opt/nextcloud/scripts/15min.sh
#!/bin/sh

wget http://cloud.EXAMPLE.COM/cron.php -o /dev/null

$ chmod +x /opt/nextcloud/scripts/15min.sh

In other words, there is a directory /opt/nextcloud/scripts and in that directory we create a shell script named 15min.sh. It uses wget because the Alpine container for NextCloud does not have curl.

The Compose file used for Crond is:

version: '3.8'

services:
    crond:
        image: robogeek/crond:latest
        container_name: crond
        networks:
            - cloudnet
        volumes:
            - ...
            - /opt/nextcloud/scripts/15min.sh:/etc/periodic/15min/nextcloud:ro
            - ...

networks:
    servernet:
        external:
            name: cloudnet

This is a separate Compose file from the NextCloud Compose file discussed earlier. Going by the best practice named earlier, it is stored in /opt/crond as docker-compose.yml. The Crond service can be, and in my case is, used by multiple services running on the VPS.

Simply connect Crond to the cloudnet bridge network as shown here. That gives it access to all deployed services.

The 15min.sh script is mounted into /etc/periodic/15min and is named nextcloud. Because the Crond container uses Alpine Linux, which uses Busybox, the Cron implementation is supplied by Busybox. For folks familiar with old-school Cron (I started in 1984), configuration of the Busybox Crond is unusual. But, as pointed out in Scheduling background tasks using cron in a Docker container, the robogeek/crond container is only 5 MB in size versus the 222 MB required to use Debian and a more normal Cron.

In this case any script in the /etc/periodic/15min directory is executed every 15 minutes. Hence, the script shown earlier pings the NextCloud URL often enough to keep NextCloud happy.

Fixing the NextCloud "maintenance window start time" error

This issue covers certain background tasks. We just configured a Cron service that gets NextCloud to run background tasks. Some of these tasks are not time sensitive, and can be executed in the wee hours of the morning.

The (docs.nextcloud.com) NextCloud documentation contains two solutions:

  1. Login to BASH inside the NextCloud container and run an occ command.
  2. Edit the configuration file

To run the occ command, connect to the NextCloud container like so:

$ docker exec -it nextcloud_app.1.tfywzr4ixrsfja0cuz2co109m bash
root@ae0a09da9430:/var/www/html# 
exit

But, wait, as noted later in this article, there is an issue with running occ that requires using user-ID 33. This docker exec command gave us a root (user ID 0) shell inside the container.

Instead, run this:

$ docker exec -u 33 -it nextcloud_app.1.tfywzr4ixrsfja0cuz2co109m bash
www-data@ae0a09da9430:~/html$ ./occ config:system:set maintenance_window_start --type=integer --value=1
System config value maintenance_window_start set to integer 1

Adding -u 33 runs the shell as user ID 33. This occ command sets the maintenance window to start at 1AM.

Upon reloading the administrative settings page, this issue will go away.

Fixing the NextCloud database indexes issue

As the message says, the database indexes affect performance. In my case this may be a side effect of having upgraded from the version 27 container to the version 28 container.

The solution is simply to run the occ command mentioned in the message.

$ docker exec -u 33 -it nextcloud_app.1.tfywzr4ixrsfja0cuz2co109m bash
www-data@ae0a09da9430:~/html$ ./occ db:add-missing-indices
Adding additional mail_messages_msgid_idx index to the oc_mail_messages table, this can take some time...
oc_mail_messages table updated successfully.
www-data@ae0a09da9430:~/html$

Once you've done this, reload the administrative settings page, and the message will be gone. Poof.

Properly setting up to resolve "/.well-known/caldav" and "/.well-known/carddav"

To fix the issues with /.well-known/caldav and /.well-known/carddav we must return to NGINX Proxy Manager, open the configuration window, and navigate to the Custom Locations tab. If you read the NextCloud documentation, it describes setting up Apache with .htaccess, and in NGINX setting up location directives in the NGINX config file. With N.P.M. we can use this Custom Locations tab.

This configures the two URL locations to pass requests to a back-end URL in the NextCloud instance. The URL locations starting with /.well-known are defined by the Internet standards committees, and are a "well known" URL path through which to access specific services. The NextCloud documentation says to pass these locations to /remote.php/dav/, and for the purpose of NGINX Proxy Manager configuration we must enter nextcloud/remote.php/dav/.

There are two locations to enter, so click the Add Location button twice. Enter the /.well-known/caldav and /.well-known/carddav locations as shown in the image. For each, the Scheme box will contain http, the Forward Hostname / IP box will contain nextcloud/remote.php/dav/, and the Forward/Port box will contain 80. Below this box is instructions reading Use 1.1.1.1/path for sub-folder forwarding, which means the text starts with the host name or IP address, and then continues with any additional path. The hostname is nextcloud and the path is /remote.php/dav/. The hostname should correspond to the container name in your Compose file.

As soon as you save the N.P.M. configuration, it will rebuild the NGINX config file, and then in the NextCloud overview page the issues named above will be resolved.

Fixing the remote address was identified as "10.0.0.2" error

In this case the documentation link is misleading. The documentation says to edit config/config.php and to add entries to the trusted_proxies array.

This file will be in the directory mounted to the host file system, such as /opt/nextcloud/data.

Going by the documentation it should be this simple:

  'trusted_proxies' =>
  array(
    0 => '10.0.0.2',
  ),

But, this doesn't change the error message.

Instead, in the (help.nextcloud.com) NextCloud support area is a discussion saying to enable the Bruteforce Settings application. You'll find this in the Apps area, under Security.

Once enabled, you find the Bruteforce settings in the Security configuration page. Scroll down to find Brute-force IP whitelist. You must then add an IPv4 CIDR to the list. For my host, 10.0.0.2, I added the CIDR 10.0.0.0/8.

Fixing the no default phone region set problem

This is a case where the documentation is absent, and the warning message is unclear as to what to do. Fortunately the fix is simple.

In the config/config.php file mentioned earlier, add the following entry:

  'default_phone_region' => 'US',

The value for default_phone_region should be your two-letter country code. The warning message helpfully includes a link to a Wikipedia page listing these codes.

Fixing the transactional file locking problem

The message is a little confusing, since it talks about Memcache, when the solution is to install REDIS. In any case, performance is important.

In the Compose file, make this change:

services:
  ...

  nextcloud:
    ...
    environment:
      ...
      - REDIS_HOST=redis
      ...
  ...
  redis:
    image: redis:alpine
    restart: always
    networks:
      - cloudnet

Adding REDIS will theoretically improve performance by caching things in memory.

If you need to install REDIS without deleting and recreating the NextCloud installation, the equivalent in config.php is approximately this:

  'filelocking.enabled' => true,
  'memcache.distributed' => '\\OC\\Memcache\\Redis',
  'memcache.locking' => '\\OC\\Memcache\\Redis',
  'redis' => 
  array (
    'host' => 'redis',
    'password' => '',
    'port' => 6379,
  ),

In the documentation, two purposes for using REDIS are given. The first is to move file locking to the REDIS server, because doing it in the database is very slow. The second is to cache some data in memory to improve performance.

Fixing the reverse proxy header configuration is incorrect problem

The link included with this message refers again to the Reverse Proxy documentation.

The Docker networks in use on this VPS are on the 10.0.x.x range. Therefore, in config/config.php, add this:

  'trusted_proxies' =>
  array(
          0 => '10.0.0.0/16',
  ),

The trusted_proxies array is defined to take either IPv4 addresses or IPv4 CIDRs. This CIDR whitelists any 10.0.x.x address. The value you choose depends on your local network configuration.

Fixing the not set or verified your email server configuration error

It's helpful that NextCloud be able to send notifications. For example, an appointment entered in a NextCloud calendar should send you a reminder e-mail, just like the calendar system from a certain G-flavored system.

The error message contains a link to the Basic Settings section in which you can configure an outgoing SMTP server. To do this you'll need to discover the particulars of the SMTP service you plan to use. For this section, I'm assuming your NextCloud instance is hosted on a web hosting provider which runs an SMTP service for its clients.

In my case, I use Dreamhost, and it offers free mail service including any number of e-mail boxes (full SMTP and IMAP support) with a webmail client. Their support area has some help documents describing configuration of an e-mail client, and configuring the WP Mail SMTP plugin for Wordpress. Between the two it's feasible to work out the following required parameters:

  • What SMTP encryption to use - either STARTTLS or SSL
  • What SMTP port to use - SSL is usually port 465, and STARTTLS is usually port 587
  • What SMTP host to use
  • Are "login" credentials required to use SMTP? Such as a user-name and password combination.
  • What IMAP encryption to use - either STARTTLS or SSL
  • What IMAP port to use - STARTTLS is port 993
  • What IMAP host to use
  • What IMAP "login" credentials to use

I found it helpful to first configure the NextCloud email client, as well as the web hosting provider webmail client, to test both sending and receiving e-mail to/from the email address. To do this, in the Administration menu there is an Apps choice. These applications extend NextCloud's capabilities, and are the primary reason for using NextCloud. The Mail application is in both the Featured and Office & Text collections. Simply enable the application, and a mail-envelope icon shows up in the top bar.

It's helpful to set up a brand new email address just for the purpose of sending notifications from NextCloud. For Dreamhost, the control panel has an area named Manage Email in which you create e-mail addresses. Create a fully managed e-mail address, and select a good password. From this section of the control panel, there's a button giving direct access to the webmail client.

Login to the webmail client, and then send and receive a few e-mails with another e-mail address. That lets you verify that the e-mail address is working.

Also login to the NextCloud e-mail client. Start by clicking on the envelope icon shown here.

For your first time, you'll be asked to connect to your mail account.

Simply fill in the settings you gathered earlier. It will ask for both IMAP and SMTP settings, giving you a chance to test both.

You'll see the same e-mails in both user interfaces. That's because the IMAP connection is, in both cases, going to the same IMAP service. You can also use an e-mail client like Thunderbird to do the same.

For testing, you must have a completely separate e-mail account.

After ensuring the e-mail address works, it's safe to proceed to the Basic Settings page.

A warning first about the environment variables for configuring NextCloud. The DockerHub README shows some variables for SMTP settings. It's possible to configure the notification e-mail service this way. If you do this, the configuration form on the Basic Settings page will be frustratingly difficult to use. You'll enter the configuration, only to have the configuration reset to the values from the environment variables.

Either configure SMTP using environment variables or using the Basic Settings page. Trying to do both is an exercise in frustration.

NextCloud SMTP configuration panel, image by David Herron

Having gathered the required settings earlier, you simply plug them into this form.

With Dreamhost, the SMTP service uses STARTTLS, at smtp.dreamhost.com, port 587. The credentials are the e-mail address you created earlier, along with the login password.

As it says, the Send email button lets you verify that things are working. If not, there will be an inscrutable error message which tells you to consult your mail server logs. Good luck on figuring out where that is. But, by preverifying the settings using the NextCloud E-Mail app, you understand the SMTP settings, and this form should just work.

The test e-mail will arrive in the e-mail you configured in the personal settings of your NextCloud account.

Success is indicated by receiving this e-mail:

Successfully sent test email, image by David Herron

Congratulations on getting NextCloud e-mail notification setup.

Fixing an error when the PHP OPcache buffer is full

The status may include this message:

The PHP OPcache module is not properly configured. The OPcache buffer is nearly full. To assure that all scripts can be hold in cache, it is recommended to apply "opcache.memory_consumption" to your PHP configuration with a value higher than "128".

The message includes a (docs.nextcloud.com) link to the NextCloud documentation.

It boils down to making this change in data/config/config.php:

$ sudo tail data/config/config.php
  'maintenance' => false,
  'loglevel' => 2,
  'maintenance_window_start' => 1,
  'opcache.memory_consumption' => 192,
);

That final line sets the value mentioned above.

After restarting the Docker containers, the message should disappear from the NextCloud overview page. But, consider what this message says, namely that the cache is of a certain size, and that it was full. It's likely that over time the cache fills up, and that initially after restarting the container the cache has not yet filled up. Therefore testing if this is the correct cache size likely requires revisiting this page after a week or two.

The number, 192, was chosen solely because it is the sum of 128 and 64. It may be a larger, or smaller, cache than is required.

Performing a security scan of your NextCloud instance

The settings page also includes a link to a security scanning service at (scan.nextcloud.com) https://scan.nextcloud.com/

Simply go to that page, and enter the public URL for your NextCloud instance. In my case, after performing all the above updates, my server got an A+ rating.

Configuring NextCloud to use the GMAIL SMTP service to send e-mails

Earlier we configured NextCloud to sent emails (password resets, reminders, etc) using your web hosting provider SMTP service. A popular alternative is to use GMAIL to send email via SMTP. GMAIL isn't just a place to read and write e-mails. You can configure desktop e-mail clients, like Thunderbird, to read and send e-mail via GMAIL, and you can do the same with website software like NextCloud.

You probably have a Google Account, and therefore have a GMAIL account. It's possible to configure NextCloud to use the GMAIL SMTP server.

NextCloud is still installed on your web hosting service as discussed above. What's different is the SMTP settings on the Basic Settings page we visited earlier.

You're not limited to your web hosting provider, or to GMAIL, for an SMTP server. There are many 3rd party paid SMTP services, and it's also possible to install your own SMTP server. No matter the SMTP service you're using, whether it's GMAIL or otherwise, you simply put the particulars in the NextCloud SMTP configuration screen.

In my case, the domain on which I've hosted NextCloud is associated with a Google Workspace account. Therefore the email for this domain is handled by the GMAIL part of Workspace.

Earlier we configured NextCloud to use the SMTP server operated by your web hosting provider. That used a user-name and password to authenticate with the SMTP server. It is desired for all SMTP servers to require authentication as one of a range of measures to fight against SPAM.

The process to configure NextCloud to use GMAIL's SMTP server is is similar to how we configured NextCloud to use the web hosting provider SMTP service. It takes these steps:

  • We'll first get an App Password for the Google Account,
  • then we'll configure the NextCloud mail agent to access the GMAIL on that account to test the user-name and app password combination,
  • then we'll configure NextCloud to use these credentials.

Getting an App Password for a Google Account
When using the GMAIL SMTP server, one cannot simply use the password for your Google Account to authenticate with the GMAIL SMTP server. Instead it is necessary to set up an App Password for your Google Account. See: (support.google.com) https://support.google.com/accounts/answer/185833

Notice that Google recommends against setting up App Passwords. Such passwords are a text string just like a regular password, they're simply provisioned by Google and are relatively unguessable. If that password leaks to the public the miscreants can hijack your Google account.

To do this, while logged in to GMAIL click on the identity icon in the upper-right corner, and you'll see a button marked Manage Google Account.

The account menu, image by David Herron

Click on the Manage your Google Account button. On the subsequent page, then click on the Security choice in the left-hand menu.

Google account navigation menu, image by David Herron

In that page find the section named Signing into Google, or How you sign in to Google.

How to sign in to Google, image by David Herron

In that section click on 2-Step Verification, and scroll to the bottom of the page where you'll find App Passwords.

Start creating an App Password, image by David Herron

This page shows the list of App Passwords, and lets you create a new one. To start, type in the name of the application for which the password is created. In this case, use NextCloud. Google may ask you to verify yourself in this process.

The generated App Password, image by David Herron

This shows your generated App Password. This is the only time in this or any other universe where you'll be shown this password. As the instructions say, save this somewhere secure. When finished, click Done.

The App Password you just created is now shown on the list.

I just showed you the generated password. This means I've leaked the password to the public. If your password leaks, it's necessary to revoke the leaked password, and create/use a new one.

To revoke a password, click on the trash-can icon shown here. Simply click on that button, and the entry will disappear from the list. Poof.

Setting up NextCloud E-Mail to use GMAIL with App Password As we did earlier, in NextCloud navigate to the e-mail section. If you do not have a currently configured e-mail account, you'll be asked for configuration. If you have an account setup, delete the account so that we can configure a new one.

For GMAIL, I found it's possible to use the Auto mode for configuring use of a GMAIL account. Simply enter the email address for your Google account, then enter the App Password that Google gave you, but remove the spaces. Instead of entering xcqv xnmo ucvd idhn, enter xcqvxnmoucvdidhn.

The settings which came up for me are:

  • IMAP Host: imap.gmail.com
  • IMAP Security: SSL/TLS
  • IMAP Port: 993
  • IMAP User: my e-mail address
  • IMAP Password: the App Password (with spaces removed)
  • SMTP Host: smtp.gmail.com
  • SMTP Security: SSL/TLS
  • SMTP Port: 465
  • SMTP User: my e-mail address
  • SMTP Password: the App Password

Test sending an email:

Sending a test email in NextCloud, image by David Herron

Notice that the To address is a button with an X choice, and that the Send button is enabled. To achieve this status, it's not enough to just enter the To address text. NextCloud shows you a dropdown menu with the address. Click on that, and the screen will shown up as shown here.

After sending the email, check the destination account.

Reading the test email, image by David Herron

So long as you get this, you've verified that the NextCloud email client can send and receive emails on GMAIL using an App Password.

Configuring NextCloud to use a GMAIL App Password for sending notifications Now that we've verified that the App Password works, let's configure the Basic Settings as we did before.

NextCloud basic settings to use GMAIL, image by David Herron

This shows the settings determined earlier entered into the NextCloud Basic Settings for the email server.

  • Send mode SMTP with Encryption set to SSL
  • From address set to YOUR-EMAIL at gmail.com
  • Authentication method set to Login with Authentication required
  • Server address set to smtp.gmail.com on port 465
  • Credentials YOUR-EMAIL@gmail.com and the App Password as you used it earlier.

After completing that there is a button for sending a test email. Make sure to first click the Save button, then click on the Send email button. If all is well you'll shortly receive an email.

Successfully sent test email, image by David Herron

A caveat with using GMAIL to send emails

All the sent emails land in the Sent folder of the GMAIL account.

This means that Google's information snarfing operation will collect data from those Sent emails. It also means the emails sent by NextCloud use up the email quota of that Google account.

You may prefer to use a different SMTP/IMAP account than GMAIL.

What to do if NextCloud is stuck in maintenance mode

While administering my NextCloud instance, I wanted to update the installed applications. This is done by selecting the Apps item in the menu. The list of installed applications shows buttons for any App which can be updated.

Somehow in my case, this got NextCloud into maintenance mode, and it stayed in that mode for a couple of days. When in this mode, any access to NextCloud shows this screen:

NextCloud maintenance mode, image by David Herron

To get it out of this mode requires starting a command-line shell inside the Docker image, then running the occ command.

I started by using ssh to login to my virtual private server. On the VPS, I ran this:

$ docker ps

  --- or ---

$ docker ps | grep nextcloud

This lists the currently executing Docker containers, and the actual container name. Because this is launched with docker compose the actual container name includes a code number.

Next:

$ docker exec -it nextcloud_app.1.pdcj8d464luc49wdd9niltlz8 bash

This executes bash inside the named container. Notice that this has the code number for the container.

The command-line shell starts in the /var/www/html directory, and among the files there is occ which has execute permissions:

# ls -l occ
-rwxr-xr-x 1 www-data www-data 283 Nov  2 20:49 occ

The command to run is occ maintenance:mode --off, but because the shell is executing as user ID 0 (a.k.a. root) this error is printed:

# ./occ maintenance:mode --off
Console has to be executed with the user that owns the file config/config.php
Current user id: 0
Owner id of config.php: 33

The output goes on to recommend using sudo -u #33, but the sudo command is not installed in this container. Resolving this message requires getting a command shell with user ID 33.

After some experimentation, this did the trick:

# su www-data --shell /bin/bash

The NextCloud image chosen in the Compose file is based on Apache, which uses the www-data user name. In /etc/password that user has the ID 33, matching the error message shown above.

The faster method is to modify the docker exec command to this:

$ docker exec -u 33 -it CONTAINER-NAME bash

This directly starts the shell inside the container with the correct user ID.

As a result, a new command shell is started with the correct user ID, and we can run this:

$ ./occ maintenance:mode --off
Maintenance mode disabled

And, refreshing the web browser tab gets NextCloud back into normal mode.

NOTE that forcibly turning off maintenance mode does not fix any underlying problem. If there was a problem, that problem still exists.

Summary

NextCloud is an excellent tool for replacing many commercial cloud services. We wish that setup would be more straight-forward, since that would open its use to even more people.

As we saw, the community-maintained Docker container for NextCloud does not result in a smooth experience after deployment. Instead there are several issues to resolve, some of which are inscrutable. But, the recommendations above are mostly easy to implement and take care of all the issues I saw during setup.

About the Author(s)

(davidherron.com) David Herron : David Herron is a writer and software engineer focusing on the wise use of technology. He is especially interested in clean energy technologies like solar power, wind power, and electric cars. David worked for nearly 30 years in Silicon Valley on software ranging from electronic mail systems, to video streaming, to the Java programming language, and has published several books on Node.js programming and electric vehicles.