Skip to main content
Docker

How to Install Nextcloud with Docker on Your Linux Server

You can now ditch Google Drive or Dropbox and create you own cloud server with Nextcloud and Docker.

Debdut Chakraborty

Warp Terminal

Nextcloud is the perfect solution for a self-hosted Google Drive or Dropbox alternative.

I am not going to tell you why you should use Nextcloud. Instead, I am going to show you how to install Nextcloud server with Docker containers.

The tutorial uses Ngnix reverse proxy set up so that you can deploy your Nextcloud instance with SSL. This way, your Nextcloud deployment URL will be using HTTPS and you'll be transferring files securely.

Towards the end of the tutorial, I'll share some tips for Linode cloud users for reducing the effort on Nextcloud deployment.

Linode | The Independent Open Cloud for Developers
Our mission is to accelerate innovation by making cloud computing simple, affordable, and accessible to all.

Prerequisites

Before moving forward, some things need to be taken care of. Here's what you need:

  • A Linux server either a physical one, a virtual machine or in a cloud server.
  • Docker and Docker Compose installed on your Linux server. If you need help follow docker installation guide on Ubuntu and CentOS. Similarly, you can follow the docker-compose installation tutorials on Ubuntu and CentOS.
  • Some knowledge of Docker and Docker Compose is good to have.
  • A domain name. This deployment, like all the other ones from Linux Handbook, is done under an actual domain name with HTTPS.
  • Some experience with shell and Linux commands since there's a lot of movement in there.
  • Access to an SMTP service like Sendgrid. You'll need it for sending email notifications, password reset etc.
  • Time and patience.

Deploying Nextcloud server with Docker in reverse proxy

Let's see the steps one by one.

Step 1: Set up reverse proxy

With reverse proxy, you can deploy several web services on the same server. This is not optional because you need let's Encrypt container for SSL.

There are two ways you can set the Ngnix reverse proxy..

If you're not using Linode, please go through my article on how to set up nginx-reverse-proxy with Docker.

How to Use Nginx Reverse Proxy With Multiple Docker Apps
Learn how you can deploy multiple web services on the same server using Nginx reverse proxy and docker containers.

If you are using Linode, I recommend you use our reverse-proxy-jwilder StackScript to easily deploy your server with everything already set up for you.

The reverse proxy deployment should be done using a separate Compose file so that you can restart or update web-services without disturbing your reverse proxy setup.

I have already prepared the compose files in our public GitHub repository. Since this is not a detailed article about the reverse-proxy deployment, I shall not go into the Compose file details.

You can either use git, or wget to download the files. If using git, clone the whole repository:

git clone https://github.com/linuxhandbook/tutorial-snippets && \
	cd tutorial-snippets/Reverse_Proxy

Otherwise, just download the necessary files:

mkdir -p ~/Reverse_Proxy && cd ~/Reverse_Proxy
for file in max_upload_size.conf env.example docker-compose.yaml; do
	wget https://raw.githubusercontent.com/linuxhandbook/tutorial-snippets/main/Reverse_Proxy/${file}
done

There are three files here:

  • env.example: Rename it to .env and change the value of DEFAULT_EMAIL to your email
  • max_upload_size.conf: This file makes sure that you can upload files as big as 1 GB in size (the default is 2 MB).
  • docker-compose.yaml: Biggest of them all. Discussed in brief in the next paragraph.

Create a docker network named net. This is used in the docker-compose.yaml file.

docker network create net

The docker-compose file looks like this:

Finally, deploy the containers

docker-compose up -d

On a successful deployment, you should get a 503 when trying to visit the IP address of the server that is hosting this reverse-proxy. That's okay. You don't have a web service running on it just yet.

Ngnix reverse proxy without any service running

Step 2: Deploy Nextcloud

There are two components here: one is the database, another is Nextcloud itself, or rather let's call it the frontend.

For the backend database, any MySQL-based database will work. I'm going with MariaDB, especially the image tag (or version) 10.5.9.

For Nextcloud, I'll use the version 21.0.0, this is the latest at the time of writing this article.

Therefore, the images used are

  • mariadb:10.5.9
  • nextcloud:21.0.0
If you are using this tutorial in the future (from present time reference) and there is a much newer version of Nextcloud and MariaDB, please use those versions.

The skeleton files, i.e. the compose file and the env files are already uploaded to our public GitHub repository. You can either download that or rewrite them while reading the explanations.

I recommend you download the files, and then go through everything to understand what's going on, there's no need for you to rewrite everything from scratch.

You can either clone our whole GitHub repository, or just download the necessary files.

If you cloned the "tutorial-snippets" repository while deploying the reverse-proxy, just change your current directory to tutorial-snippets/Nextcloud.

The working git command is as follows:

git clone https://github.com/linuxhandbook/tutorial-snippets && \
    cd tutorial-snippets/Nextcloud

Otherwise, use the following shell code to create a directory named "Nextcloud" and download the files in there.

mkdir -p ~/Nextcloud && cd ~/Nextcloud
for file in env.example docker-compose.yaml; do
    wget https://raw.githubusercontent.com/linuxhandbook/tutorial-snippets/main/Nextcloud/${file}
done

Copy the env.example file to .env . You'll be editing this file later for the environment variables. Keeping the original file is just for the sake of backup, nothing else.

cp env.example .env

Now, let me go through the services definitions:

1. NCDatabase

The NCDatabase service looks like this:

NCDatabase:
	image: "mariadb:10.5.9"

	volumes:
		- "NCMariaDB:/var/lib/mysql"

	environment:
		- MYSQL_ROOT_PASSWORD
		- MYSQL_RANDOM_ROOT_PASSWORD
		- MYSQL_DATABASE
		- MYSQL_USER
		- MYSQL_PASSWORD

	restart: "on-failure"
	networks: ["common"]

This is the database service, and as stated previously, it uses the mariadb:10.5.9 image as its blueprint.

For persistent storage, I'm using a volume named NCMariaDB, it is mounted at /var/lib/mysql, where MariaDB stores its data.

The environment variables are handled using a .env file, I'll talk about that in a moment.

I like the on-failure restart policy, but you're free to choose unless-stopped or always. You may want to read more on restart policy in Docker.

The common network is common between this and the frontend service, it is there to make sure communication is possible between these containers.

Environment Variables

This is a Docker-based deployment, you are bound to set up some environment variables. Now open this .env file in your favorite text editor and start changing the values as the following:

MYSQL_ROOT_PASSWORD or MYSQL_RANDOM_ROOT_PASSWORD: Either set MYSQL_RANDOM_ROOT_PASSWORD to 1 or set a strong root password for MariaDB. Use openssl to generate a random password.

MYSQL_DATABASE & MYSQL_USER: There are some defaults set, but you can change these if necessary. Set these to your preferred database name and user name respectively.

MYSQL_PASSWORD: Password for the user (MYSQL_USER) that will have access to the main MariaDB database (MYSQL_DATABASE).

MYSQL_HOST: This is the service name of the database container. If you're not going to change the service name in the Compose File, leave this as it is.

2. NCFrontend

This is the Nextcloud frontend service. This service is as simple as the previous one. Take a look:

NCFrontend:
	image: "nextcloud:21.0.0"

	volumes: 
	  - "NCData:/var/www/html"

	environment:
		- LETSENCRYPT_HOST
		- VIRTUAL_HOST
		- TRUSTED_PROXIES
		- OVERWRITEPROTOCOL
		- MYSQL_DATABASE
		- MYSQL_USER
		- MYSQL_PASSWORD
		- MYSQL_HOST
		- SMTP_HOST
		- SMTP_PORT
		- SMTP_NAME
		- SMTP_PASSWORD
		- MAIL_FROM_ADDRESS
		- NEXTCLOUD_TRUSTED_DOMAINS
		- NEXTCLOUD_ADMIN_USER
		- NEXTCLOUD_ADMIN_PASSWORD

	depends_on:
		- "NCDatabase"
	networks: ["net", "common"]

Image used is nextcloud:21.0.0, as I previously said, is the latest version at the time of this writing.

To make sure you keep your data safe, and don't lose it in an unfortunate event of a simple container restart, data must be persisted. Nextcloud saves its data/information in /var/www/html, so this location is made persistent using a volume named NCData.

The depends_on array is an interesting one. It makes sure that the values, i.e. the services mentioned in it are deployed first before the current one starts.

Here, I'm making sure that the database is starting before Nextcloud itself, to avoid any connection issues.

You might still see some issues in the logs, because a successful container start doesn't indicate that the intended processes inside the container have also started successfully. They can take more time. In our case, mysqld takes a little bit more time to start, which is why you might see a couple of errors in the logs until finally a successful connection is made.

There are two networks. The first one is net, which was also part of the reverse-proxy deployment. This is necessary because the reverse-proxy needs to be able to communicate with the proxied services, i.e. Nextcloud. The common network is for the nextcloud and database containers to be able to communicate successfully.

Docker Compose creates a default network for all its services in a Compose file. But since NCFrontend service is already connected to the net network, Docker Compose is not going to create that default network anymore, which is why you have to create a custom network like "common" to make the communication happen.

Environment Variables

Open the .env file (the same one you used for MariaDB) in your favorite text editor and start changing the values as the following:

LETSENCRYPT_HOST, VIRTUAL_HOST & NEXTCLOUD_TRUSTED_DOMAINS: Set these to the domain/subdomain you want to host your Nextcloud instance on.

TRUSTED_PROXIES: The subnet of the network, shared by the reverse proxy and this frontend. You can get the subnet using the following command (make sure jq is installed)

docker inspect -f '{{ json .IPAM.Config }}' net | jq -r .[].Subnet

OVERWRITEPROTOCOL: The overwriteprotocol parameter is used to set the protocol of the proxy. As we're using HTTPS, set this to HTTPS.

SMTP configuration is optional. For this article, I'm going to use SendGrid as an example. Consult your SMTP server documentation for more appropriate values to the following environment variables.

SMTP_HOST & SMTP_PORT: The SMTP server address and the port it'll be listening on, for SendGrid it is smtp.sendgrid.net and port 587 for automatic TLS.

SMTP_NAME & SMTP_PASSWORD: The username & password for authentication. For SendGrid the value of the username is very consistent. It is apikey. For the password, it's going to be your API key.

MAIL_FROM_ADDRESS: The value of the From SMTP header. Set this to something like [email protected].

NEXTCLOUD_ADMIN_USER & NEXTCLOUD_ADMIN_PASSWORD: Instead of using the web UI the first time to create the admin user, you can instead create that right at the deployment stage through these variables. Set these to your admin user's username and password. If you left it, you'll be prompted to create an account the first time you launch Nextcloud.

Volumes

I have two internal volumes defined in this network, NCMariaDB for MariaDB and NCData for Nextcloud. Whether to keep these internal or external is up to you.

Many will say it's risky to keep these internal since you can easily make the mistake of using docker-compose down -v and remove the volumes along with the containers. At the same time, with external volumes, you can make the mistake of docker volume prune and delete all your data.

Decide which one is going to be safer for you. If you decide to make them external, open the Compose file and change the volumes definition to something like this:-

volumes:
  NCMariaDB:
    external: true
  NCData:
    external: true

Afterward, create the volumes:

for volume in NCMariaDB NCData; do
  docker volume create ${volume}
done

Networks

There's not much here. You'll notice there are two networks defined. One is for the frontend and reverse-proxy, and the other one is for the frontend and the backend to be able to communicate.

The database container and nextcloud frontend have a common network named "common", this is there for these two containers to be able to communicate with each other. You can make this internal, which will limit the database container from accessing the public internet, but I am not sure what advantage[s] you might get from this.

Still if you want to do this, it should look like this:

networks:
	net:
		external: true
	common:
		internal: true

Finally, deploying Nextcloud

There's nothing else left to do. Just run the following command

docker-compose up -d

The necessary images are going to be pulled and then deployed.

Once deployed, there should be a total of four containers running on your server.

debdut@localhost:~$ docker ps -a
CONTAINER ID   IMAGE                                           COMMAND                  CREATED       STATUS       PORTS                                      NAMES
1dce1c7909fe   jrcs/letsencrypt-nginx-proxy-companion:latest   "/bin/bash /app/entr…"   7 hours ago   Up 7 hours                                              reverse_proxy_LetsencryptCompanion_1
d29719999132   jwilder/nginx-proxy:latest                      "/app/docker-entrypo…"   7 hours ago   Up 7 hours   0.0.0.0:80->80/tcp, 0.0.0.0:443->443/tcp   reverse_proxy_NginxProxy_1
cd719cb2a677   nextcloud:21.0.0                                "/entrypoint.sh apac…"   7 hours ago   Up 7 hours   80/tcp                                     nextcloud_NCFrontend_1
60dff2062aa5   mariadb:10.5.9                                  "docker-entrypoint.s…"   7 hours ago   Up 7 hours   3306/tcp                                   nextcloud_NCDatabase_1

You may have more containers running as well if there were containers running previously. The bottom line is this Nextcloud deployment consists of four containers, the nginx container, the letsencrypt companion container, mariadb container and finally the actual nextcloud container.

Post deployment

Before wrapping this up, I wanted to mention one quick thing you may wanna know post deployment.

First open your browser and head over to the domain this Nextcloud instance is hosted on (VIRTUAL_HOST). You should see a screen similar to this, if you did not set the admin user using the compose file

First Log In Nextcloud

Since the database environment variables are shared through the common .env file, you won't see the more common web install UI that asks for the database information like hostname, port, database username password.

A similar checkbox can be seen there as well. I recommend you uncheck this box and install whichever apps you need later on from the app list.

App List for Nextcloud

For more post deployment tips, read this awesome article written by my colleague Avimanyu:

10 Helpful Tips for Managing a Nextcloud Docker Instance
Some helpful advice to keep in mind and follow in practice while you self-host your Nextcloud instance with Docker!

That's it. I hope this detailed tutorial helps you with your Nextcloud server installation with Docker. If you have questions or suggestions, please let me know in the comment section and I'll be glad to help you out.