Practical private cloud: How to self-host Nextcloud and Collabora on Ubuntu backed by HTTPS

tutorial

#1

Nextcloud provides file hosting. The Collabora Online plugin allows for online collaborative document editing within the Nextcloud. They’re easy to deploy and manage with Juju.

Requirements

To make your way through this tutorial, you will need:

Establishing a Juju controller

We require a controller. You have two options:

  • Use the hosted JAAS controller: juju login jaas. This requires you to delegate your cloud credentials to Canonical, but does not incur any extra cost.
  • Otherwise use the juju bootstrap command. Use the juju bootstrap command. Follow Getting Started with Juju for detailed instructions.

Creating a model

A model is a workspace for our applications. It houses machines, and applications. Complex models also include other bits and pieces like networking spaces and persistent storage volumes.

juju add-model privcloud
Added 'privcloud' model on aws/us-west-1 with credential '<credential>' for user `<user>`

Adding machines

Using your own computer hardware

If you have your own server hardware, you can make use of the manual cloud to register your computers with Juju.

juju add-cloud

Begins an interactive prompt where you will be asked to give a name to your cloud and SSH login details (noah@10.10.10.100 in this example) :

Cloud Types
  lxd
  maas
  manual
  openstack
  vsphere

Select cloud type: manual

Enter a name for your manual cloud: home

Enter the controller's hostname or IP address: noah@10.10.10.100

Cloud "home" successfully added
You may bootstrap with 'juju bootstrap home'
juju bootstrap home
Need to add many machines?

Outside of the home or small office environment, your hardware will be more complex. Multi-server we recommend installing MAAS and then configuring a MAAS cloud.

We want to be conservative with our compute resources, so we’ll add a large machines manually, then deploy Nextcloud and the backing database to it.

juju add-machine --constraints="mem=8G root-disk=200G"
created machine 0

We’ll also add a small xenial (14.04) instance to manage the ssl-termination-proxy charm.

juju add-machine --series=xenial --constraints="mem=256M"
created machine 1

Deploy Nextcloud

If you would like a “1 click” install, you can use this command deploy everything together. By default, it will use several machines rather than making use of containers on the host:

juju deploy cs:~erik-lonroth/bundle/nextcloud-collabora-tls

juju deploy cs:~erik-lonroth/nextcloud --to 0
Located charm "cs:~erik-lonroth/nextcloud-3".
Deploying charm "cs:~erik-lonroth/nextcloud-3".

Nextcloud requires a database. We’ll install PostgreSQL. We allocate 120GB of storage space.

juju deploy postgresql --storage pgdata=120G --to 0
Located charm "cs:postgresql-199".
Deploying charm "cs:postgresql-199".

Multi-tenant applications: PostgreSQL and Nextcloud co-located on the same machine. To change this, we can add another unit of Nextcloud, then remove the nextcloud/0 unit. Juju provides us with the ability to start small and scale up as needed.

If you consult the juju status output, you’ll notice an angry red “blocked” message in two places:

juju status

Output:

Model      Controller  Cloud/Region   Version  SLA          Timestamp
privcloud  jaas        aws/us-west-1  2.6.8    unsupported  15:31:23+13:00

App         Version  Status   Scale  Charm       Store       Rev  OS      Notes
nextcloud            blocked      1  nextcloud   jujucharms    3  ubuntu  
postgresql  10.10    active       1  postgresql  jujucharms  199  ubuntu  

Unit           Workload  Agent      Machine  Public address  Ports     Message
nextcloud/0*   blocked   idle       0        52.53.172.164   80/tcp    Need Mysql or Postgres relation to continue
postgresql/0*  active    executing  0        52.53.172.164   5432/tcp  (start) Live master (10.10)

Machine  State    DNS            Inst id              Series  AZ          Message
0        started  52.53.172.164  i-0d1e5b3a3de5eb4ca  bionic  us-west-1c  running

Now, we need to get the two applications to talk together.

juju relate nextcloud postgresql:db

It my take a minute or two for the system to re-configure itself, but juju status will soon update itself to look more like this:

Model      Controller  Cloud/Region   Version  SLA          Timestamp
privcloud  jaas        aws/us-west-1  2.6.8    unsupported  15:35:07+13:00

App         Version  Status  Scale  Charm       Store       Rev  OS      Notes
nextcloud            active      1  nextcloud   jujucharms    3  ubuntu  
postgresql  10.10    active      1  postgresql  jujucharms  199  ubuntu  

Unit           Workload  Agent  Machine  Public address  Ports     Message
nextcloud/0*   active    idle   0        52.53.172.164   80/tcp    Ready
postgresql/0*  active    idle   0        52.53.172.164   5432/tcp  Live master (10.10)

Machine  State    DNS             Inst id              Series  AZ          Message
0        started  52.53.172.164   i-0d1e5b3a3de5eb4ca  bionic  us-west-1c  running

Accessing Nextcloud Login page

Nextcloud is now fully operational. But accessing machine 0’s public IP address (52.53.172.164) on port 80 won’t yet show you a web page. We need to inform Juju to open the firewall.

juju expose nextcloud

If we visit the IP address now, we’re presented with a login screen (and some security warnings).

What to use for the login details?

Accessing the intial log in details for Nextcloud

Juju has created an admin account on our behalf using configuration parameters available in the charm.

We can access them via the juju config commands:

juju config nextcloud admin-username
admin
juju config nextcloud admin-password
mypassword

Entering these values into the form should present you with the Nextcloud application. Take the opportunity to change the admin account’s password and create a non-admin user account.

it is possible to set your own admin password at deployment time via the --config option, but this was omitted from the earlier steps for simplicity.

Adding HTTPS

You now need to add a DNS record to a domain for nextcloud. We’ll assume cloud.example.com. The A record needs to point at the IP address of the machine hosting the ssl-termination-proxy/0 unit.

An easy way to fetch the relevant IP address is to use the filtering and formatting options of the juju status command:

juju status ssl-termination-proxy/0 --format=line

Produces

- ssl-termination-proxy/0: 54.215.139.236 (agent:idle, workload:active) 80/tcp, 443/tcp

With that information available, add the equivalent DNS entry:

cloud 	A 	54.215.139.236	3600

Now, we set the config options for the relevant applications, we need to open the proxy to the Internet and add a relation between the ssl-termination-proxy and nextcloud-fqdn.

juju config nextcloud fqdn=cloud.example.com
juju config nextcloud-fqdn fqdns=cloud.example.com
juju expose ssl-termination-proxy 
juju relate ssl-termination-proxy nextcloud-fqdn:ssl-termination

After a minute or so, juju status output will converge to something that looks like this:

juju status
Model      Controller  Cloud/Region   Version  SLA          Timestamp
privcloud  jaas        aws/us-west-1  2.6.8    unsupported  16:14:23+13:00

App                    Version   Status  Scale  Charm                  Store       Rev  OS      Notes
nextcloud              16.0.1.1  active      1  nextcloud              jujucharms    3  ubuntu  exposed
nextcloud-fqdn                   active      1  ssl-termination-fqdn   jujucharms    5  ubuntu  
postgresql             10.10     active      1  postgresql             jujucharms  199  ubuntu  
ssl-termination-proxy            active      1  ssl-termination-proxy  jujucharms   15  ubuntu  exposed

Unit                      Workload  Agent  Machine  Public address  Ports           Message
nextcloud/0*              active    idle   0        52.53.172.164   80/tcp          Nextcloud is OK.
postgresql/0*             active    idle   0        52.53.172.164   5432/tcp        Live master (10.10)
ssl-termination-proxy/0*  active    idle   1        54.215.139.236  80/tcp,443/tcp  Ready (cloud.example.com)
  nextcloud-fqdn/0*       active    idle            54.215.139.236                  Ready

Machine  State    DNS             Inst id              Series  AZ          Message
0        started  52.53.172.164   i-0d1e5b3a3de5eb4ca  bionic  us-west-1c  running
1        started  54.215.139.236  i-03d027ce3a8f9fc2e  xenial  us-west-1b  running

If yo you now access the page, you might be surprised at what you encounter:

Okay. The security warnings from the browser have gone, but a new one from Nextcloud has popped up. But that’s okay. We can use juju ssh to make the recommended setting change.

Access remote shell securely

Juju provides a helper command that understands how to connect to units directly without needing to refer back to their IP addresses:

juju ssh nextcloud/0

Alter Nextcloud trusted_domains setting

First, we need to find where the application is stored. We’ll use the find command to look for the file that

sudo find / -name 'config.sample.php' 2>/dev/null
/var/www/nextcloud/config/config.sample.php

Let’s look inside that directory:

ls /var/www/nextcloud/config/
CAN_INSTALL  config.php  config.sample.php

Great. config.php definitely looks like what we want. Let’s make a backup and edit that file.

cd /var/www/nextcloud/config/
sudo cp config.php config.backup.php

Use your favourite editor: to edit the

sudo nano config.php

Edit the ‘trusted_domains’ line so that it includes your domain name:

<?php
$CONFIG = array (
   // ...
  'trusted_domains' => array ('cloud.example.com'),
  // ...
);

Save the file.

Access Nextcloud over HTTPS

Visiting your domain name with your browser should present you with a login page with no security warnings:

Deploying Collabora

This section will be faster, as it is mostly a duplication of the steps taken for Nextcloud.

juju deploy cs:~erik-lonroth/collabora --config nextcloud_domain=cloud.example.com
juju deploy cs:~tengu-team/ssl-termination-fqdn collabora-fqdn --config fqdns=docs.example.com

While that is deploying, add a DNS record for your Collabora. Here is an example:

docs 	A 	54.215.139.236	3600

Now, add the relations. After they’re added, your applications will automatically configure themselves.

juju relate collabora:website collabora-fqdn:website
juju relate collabora-fqdn:ssl-termination ssl-termination-proxy:ssl-termination

Install the Collabora Online plugin for Nextcloud

As a single script

Juju is asynchronous and declarative. The commands in this tutorial can be executed in any order and will be resolved by Juju. Here they are as a single script that you can customise (be sure to update the configuration values):

juju deploy cs:~erik-lonroth/nextcloud
juju deploy cs:~erik-lonroth/collabora
juju deploy postgresql --storage pgdata=100G
juju deploy cs:~tengu-team/ssl-termination-proxy
juju deploy cs:~tengu-team/ssl-termination-fqdn collabora-fqdn
juju deploy cs:~tengu-team/ssl-termination-fqdn nextcloud-fqdn

# database configuration
juju relate postgresql:db nextcloud:postgres

# nextcloud configuration
juju relate nextcloud:website nextcloud-fqdn:website
juju relate nextcloud-fqdn:ssl-termination ssl-termination-proxy:ssl-termination
juju config nextcloud fqdn=cloud.example.com

# collabora configuration
juju relate collabora:website collabora-fqdn:website
juju relate collabora-fqdn:ssl-termination ssl-termination-proxy:ssl-termination
juju config collabora nextcloud_domain=cloud.example.com
juju config collabora-fqdn fqdns=docs.example.com

# networking
juju expose ssl-termination-proxy

Acknowledgements

Juju community member @erik-lonroth built the nextcloud and collabora charms to enable this.


#2

The nextcloud charm has a juju-action for adding trusted domains @timClicks


#3

Oh cool! That simplifies things greatly.


#4

By the way, if you’re wondering why I haven’t said to install the bundle - I intend to. But I also thought that it would be useful to explain what is happening.


#5

@erik-lonroth I just tried this on a new model and hit a permissions error. I will see if I can get time over the weekend to submit a fix to the charm.

$ juju run-action nextcloud/0 add-trusted-domain domain="localhost" index=1
Action queued with id: bb724530-7ebb-4727-87c7-7b9c2b740747

$ juju show-action-output --wait 0  bb724530-7ebb-4727-87c7-7b9c2b740747
results:
  result-map:
    message: |-
      Cannot write into "config" directory!
      This can usually be fixed by giving the webserver write access to the config directory
      See https://docs.nextcloud.com/server/16/go.php?to=admin-dir_permissions

      Or, if you prefer to keep config.php file read only, set the option "config_is_read_only" to true in it.
      See https://docs.nextcloud.com/server/16/go.php?to=admin-config
    time-completed: Wed Oct 23 20:03:23 UTC 2019
status: completed
timing:
  completed: 2019-10-23 20:03:24 +0000 UTC
  enqueued: 2019-10-23 20:03:02 +0000 UTC
  started: 2019-10-23 20:03:23 +0000 UTC