Nextcloud snap with other services on the same server

Nextcloud is a popular free and open source alternative cloud service application. By hosting it on ones own server, it gives the user the opportunity to save and share files in a safe, easily available place without having to deal with large corporations who are actively out for our data.

It is very easy to install Nextcloud on a rented VPS or your home server using Canonical's Snap technology. Snap packages offer convenience for the system administrator, and the Nextcloud snap facilitates the upgrades of the application. If you can afford to run a separate server for all the different web applications you plan to use, you have an easy task ahead of you. However, if you want to lower your cost and use the same server for multiple webapps, a reverse proxy has to be set up and configured.

In this tutorial, we take a look at the use case, when we have one computer running with a single public IP address. We assign multiple domain name (DNS) entries to this server, and set up a reverse proxy, that will check what domain name is used to call our server in the request, and it will decide what sites to provide based on that. If it is a domain name assigned to Nextcloud, it will forward the requests to the webserver inside the Nextcloud snap (which runs on the same computer). If the computer was addressed with a domain name assigned to the simple web site, it simply serves an other webpage.

I have spent a long time on the internet to find a suitable tutorial on how to do this reverse proxy setup with Nextcloud from beginning to end, but I couldn't so I decided to synthesize the information I gathered from multiple different sources. Check out the "References" section by the end, if you want to see what websites I used.

Important note: I show the terminal commands in the black boxes following the $ character. Do NOT type that character, only what follows. Lines that don't start with $, are either files that should be created, or, if appearing after a command, the expected output that you should see returned on your terminal. This tutorial does not include all the expected outputs. If you get an error message, check your spelling and try again. If you are not sure what the problem is, consult the manual of the commands used. When you see italicized words in a black box like this: $ command parameter, that means that you should change the italicized part to a value relevant to your case.

This tutorial is available in video form on YouTube and LBRY. The video version discusses each step in greater detail.

Contents

Get ready

In this tutorial, it is assumed that the user has a running server with a user that can use sudo. If you log in / ssh in to your server using the root user, you don't need to preface the commands with sudo. This tutorial was tested on Debian 10, but should work with Debian 9 and also Ubuntu. For other distributions, you will have to check how to install packages using your package manager, and find the proper equivalent packages.

In this tutorial, the ufw firewall is used.

For the initial setup, you can check out the following tutorials:

You should have already registered the domain names for the Nextcloud server and the regular webserver. In this tutorial, I am using the nextcloud.example.com domain name for the former, web.example.com for the latter.

Install the Nextcloud snap package

First, if you are not on Ubuntu you will have to install the snapd package after updating your system. To be able to work with snaps, you need to source the proper paths. Then install the core snap package.

$ sudo apt update

$ sudo apt install snapd

$ source /etc/profile.d/apps-bin-path.sh

$ sudo snap install core

Now that you have the snap package manager and the basic dependencies installed, now you can install the snap package for Nextcloud itself.

$ sudo snap install nextcloud

You can check the status of the snap package manager with the snap changes command, and you can get version information on the package using the snap info nextcloud command. Furthermore, network interfaces can be checked using the snap connections nextcloud command.

Configure Nextcloud

Next, you need to finalize the installation with the nextcloud.manual-install command. It is good practice to give the administrator user and password here, so no unauthorized person will be able to log in to the web applicaton. Wait for the script to confirm the successful installation.

$ sudo -i nextcloud.manual-install username password

Nextcloud was successfull installed

The Nextcloud snap package contains the required webserver and database programs, so if it is the only service running on the system, it is very simple to set up. However, we would like multiple applications running in parallel, so we won't need the webserver inside the snap to listen to the HTTP and HTTPS requests on the regular ports 80 and 443, as those ports will be handled by our reverse proxy.

So let's modify the listen ports of the Nextcloud install to something else, for example to 81 and 444. We won't let these ports through the firewall, so only the processes running locally will be able to request pages from the Nextcloud install. For this, we need to use the snap set command.

$ sudo snap set nextcloud ports.http=81 ports.https=444

Install Nginx

Nginx is a versatile tool that can act as both a webserver and a reverse proxy, and many more.

In this tutorial, we are going to use Nginx as both the reverse proxy to redirect the traffic to the Snap package if the server was called via the appropriate domain name, or just serve a simple website it was called via an other name. To acheive this, we will also have to let Nginx through the firewall, in this tutorial we use Ufw. Other firewall software will use different commands.

$ sudo apt install nginx

$ sudo ufw allow "Nginx Full"

Rule added

Rule added (v6)

If you use ufw, you can double check with the ufw status command whether the ports have been opened or not. You should see an output similar to this:

$ sudo ufw status

Status: active


To Action From

-- ------ ----

OpenSSH ALLOW Anywhere

Nginx Full ALLOW Anywhere

OpenSSH (v6) ALLOW Anywhere (v6)

Nginx Full (v6) ALLOW Anywhere (v6)

Set up the Nginx reverse proxy

In Nginx, we can use so-called server blocks, that define the independent websites and proxied locations that are served. These server blocks are text-based configuration files, located in the /etc/nginx/sites-available/ directory. Because you will probalby store private or even confidential (in case of a business) information on your Nextcloud server, you should not allow unencrypted (HTTP) traffic, only secure (HTTPS).

However, Nextcloud is not facing the network directly, all the traffic it receives, receives from Nginx, on the same computer, so we can let the two programs communicate with each other without encryption.

create a file called nextloud inside the aforementioned directory. My preferred editor is vim, but you can easily do the same by any other text editor, like nano.

$ sudo vim /etc/nginx/sites-available/nextcloud

or

$ sudo nano /etc/nginx/sites-available/nextcloud

Add the following to the file:

server {

listen 80;

listen [::]:80;


server_name nextcloud.example.com;

return 301 https://$host:443$request_uri;

}

server {

listen 443 ssl http2;

listen [::]:443 ssl http2;


server_name nextcloud.example.com;


client_max_body_size 0;

underscores_in_headers on;


location ~ {

proxy_set_header Host $host;

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;

add_header Front-End-Https on;


proxy_headers_hash_max_size 512;

proxy_headers_hash_bucket_size 64;


proxy_buffering off;

proxy_redirect off;

proxy_max_temp_file_size 0;

proxy_pass http://127.0.0.1:81;

}

}

Save the file and exit the text editor.

You might want to change other configurations, such as maximum uploadable file, or timeout parameters. For that, consult the Nginx manual, or see reference no. 5. below.

To make this reverse proxy setup, you need to create a symbolic link to this configuration file in the sites-enabled directory, and then use the built-in check function of Nginx to validate your configfile, then restart the systemd service of Nginx.

$ sudo ln -s /etc/nginx/sites-available/nextcloud /etc/nginx/sites-enabled/

$ sudo nginx -t

nginx: the configuration file /etc/nginx/nginx.conf syntax is ok

nginx: configuration file /etc/nginx/nginx.conf test is successful

$ sudo systemctl restart nginx

Set up Nextcloud to properly receive connections from Nginx

We have set up Nginx to handle HTTPS, and it forwards the traffic to Nextcloud without encryption. This makes the Nextcloud snap think, that it should generate HTTP links as if it was accessed through the web without encryption. This doesn't cause a problem on a webapp, as we have just set up automatic redirection from HTTP to HTTPS, but some mobile applications will deny working wit this setup.

To solve this issue, we need to force Nextcloud to generate HTTPS links whatever it sees as incoming traffic. This is done using the nextcloud.occ command.

$ sudo -i nextcloud.occ config:system:set overwriteprotocol --value="https"

nextcloud.occ config:system:set overwriteprotocol --value="https"

Now Nginx redirects the appropriate traffic to Nextcloud, and Nextcloud will generate the proper links. Next, you also need to let Nextcloud know, what is the domain it should allow the world to use to connect to it. First, let's check the current status.

$ sudo -i nextcloud.occ config:system:get trusted_domains

localhost

Nextcloud now only responds to the localhost hostname. Add an other element to this array based on your domain name (should be a same you used in the Nginx setup). You can double check if the addition was successful by listing all trusted domains again.

$ sudo -i nextcloud.occ config:system:set trusted_domains 1 --value=nextcloud.example.com

System config value trusted_domains => 1 set to string nextcloud.example.com

$ sudo -i nextcloud.occ config:system:get trusted_domains

localhost

nextcloud.example.com

Get a certificate from Let's Encrypt

For the HTTPS connection to work, we need to acquire the proper certificates for our system from a trusted third party. Luckily, this can be done very easily using the Certbot software, which has a Nginx plugin that will update the config files to use the certificates after securing them.

Before installing python3-certbot-nginx , make sure all the dependencies are installed.

Note: the backslash character at the end of the line allows us to imput a multi-line command. You can ignore that (and the > prompt), and type in all package names in one line.

$ sudo apt install python3-acme python3-certbot python3-mock \

> python3-openssl python3-pkg-resources python3-pyparsing \

> python3-zope.interface

Next, install the Nginx plugin for certbot.

$ sudo apt install python3-certbot-nginx

Before going any further, doublecheck on your firewall if the HTTPS port is open. If you followed the instructions here and allowed Nginx Full in ufw, you are ready to go.

You should obtain the certificate for the domain name registered for the Nextcloud server here. You can obtain certificates for the other services separately after setting up the other server blocks in Nginx.

Certbot will ask for your e-mail address and whether you would like to share it with the Electronic Frontier Foundation. Answer to your heart's content.

$ sudo certbot --nginx -d nextcloud.example.com

Certbot works by adding additional information for the server blocks responsible for handling the domains given after the -d switch. You can check the modifications by opening the /etc/nginx/sites-available/nextcloud file.

Certbot will automatically renew the certificates it autimatically installed the required scritps, so you don't have to worry about that. You can test the renewal process:

$ sudo certbot renew --dry-run

Now your Nextcloud service should be available by navigating your web browser to your domain name. You can log in with the username and password you used when configuring it.

Setting up a parallel web service

In the next step, to show how Nginx solves the problem of running multiple web services on the same computer, let's set up a simple webpage, hosted by Nginx itself.

First, let's create the directory where the webpage will be stored. Nginx itself can serve multiple sites, the default one is found in /var/www/html/, and only contains a single HTML file. Let's create a new directory for the site, and give permissions to our user to access and edit the contents without root privileges. I suggest to put the directory in /var/www/, and name it based on the domain name of the server, and then place a directoy named html inside, that will be accessed by the regular user. Be mindful, that in the chown command, you need to use the name of the user you want to give access to the directory. If you have more users who should edit, you should consult a tutorial on file system permissions.

$ sudo mkdir /var/www/web

$ sudo mkdir /var/www/web/html

$ sudo chown -R user:user /var/www/web/html

$ sudo chmod 755 /var/www/web/html

$ cd /var/www/web/html

Now, inside the directory, you can create your web sites in your favorite editor or copy files here from an outside source. I present you with a sample file, which will be saved as index.html in this example. You can create your file it with the editor of choice, without invoking sudo, such as $ vim index.html or $ nano index.html.

<HTML>

<HEAD>

<TITLE>Test page</TITLE>

</HEAD>

<BODY>

<H1>Welcome to the test page</H1>

<p>If you see it, the webserver works.</p>

</BODY>

</HTML>

Next, Nginx have to be made aware of this site by creating the proper configuration for the server blocks. We create the required file in /etc/nginx/sites-available/ using your favorite text editor.

$ sudo vim /etc/nginx/sites-available/web

or

$ sudo nano /etc/nginx/sites-available/web

This file will also contain the redirection directive to always use HTTPS, as well as the directory where the html files are located.

server {

listen 80;

listen [::]:80;


server_name web.example.com;

return 301 https://$host:443$request_uri;

}

server {

listen 443 ssl http2;

listen [::]:443 ssl http2;


server_name web.example.com;


root /var/www/web/html;

index index.html;


location / {

try_files $uri $uri/ =404;

}

}

Save the file, symlink it to the sites-enabled directory, check the syntax with the built-in command and restart the nginx systemd unit.

$ sudo ln -s /etc/nginx/sites-available/web /etc/nginx/sites-enabled/

$ sudo nginx -t

nginx: the configuration file /etc/nginx/nginx.conf syntax is ok

nginx: configuration file /etc/nginx/nginx.conf test is successful

$ sudo systemctl restart nginx

As you are using yet an other HTTPS service on this other domain, you need to acquire an other certificate.

$ sudo certbot --nginx -d web.example.com

Now your website should be up and running. This method can also be used to let your website appear on example.com, while nextcloud, or other services appear as a subdomain of that. To achieve this, you shoud use the server_name www.example.com exaple.com; line in the server block file.

Sources

Here's a list of the sources used to create this tutorial:

  1. Installing Snaps on Debian
  2. Nextcloud as a snap package in the official Snap Store
  3. Digital Ocean's Nextcloud tutorial for Debian 9
  4. Put Nextcloud behind a reverse proxy
  5. NextCloud frontend with Nginx SSL backend
  6. Generate HTTPS links even behind a HTTP reverse proxy
  7. The Nextcloud configuration file and documentation
  8. Digital Ocean's tutorial for setting up Let's Encrypt with Nginx
  9. Digital Ocean's tutorial for setting up server blocks with Nginx