polls http://tech.oeru.org/ en Installing NextCloud Hub with OnlyOffice on Ubuntu 18.04 http://tech.oeru.org/installing-nextcloud-hub-onlyoffice-ubuntu-1804 <span class="field field--name-title field--type-string field--label-hidden">Installing NextCloud Hub with OnlyOffice on Ubuntu 18.04</span> <div class="field field-node--field-blog-tags field-name-field-blog-tags field-type-entity-reference field-label-above"> <h3 class="field__label">Blog tags</h3> <div class="field__items"> <div class="field__item field__item--ubuntu-linux"> <span class="field__item-wrapper"><a href="/taxonomy/term/12" hreflang="en">ubuntu linux</a></span> </div> <div class="field__item field__item--_804"> <span class="field__item-wrapper"><a href="/taxonomy/term/68" hreflang="en">18.04</a></span> </div> <div class="field__item field__item--nextcloud"> <span class="field__item-wrapper"><a href="/taxonomy/term/51" hreflang="en">nextcloud</a></span> </div> <div class="field__item field__item--onlyoffice"> <span class="field__item-wrapper"><a href="/taxonomy/term/69" hreflang="en">onlyoffice</a></span> </div> <div class="field__item field__item--mariadb"> <span class="field__item-wrapper"><a href="/taxonomy/term/48" hreflang="en">mariadb</a></span> </div> <div class="field__item field__item--docker-compose"> <span class="field__item-wrapper"><a href="/taxonomy/term/25" hreflang="en">docker compose</a></span> </div> <div class="field__item field__item--docker"> <span class="field__item-wrapper"><a href="/taxonomy/term/16" hreflang="en">docker</a></span> </div> <div class="field__item field__item--php"> <span class="field__item-wrapper"><a href="/taxonomy/term/40" hreflang="en">php</a></span> </div> <div class="field__item field__item--redis"> <span class="field__item-wrapper"><a href="/taxonomy/term/21" hreflang="en">redis</a></span> </div> <div class="field__item field__item--polls"> <span class="field__item-wrapper"><a href="/taxonomy/term/70" hreflang="en">polls</a></span> </div> <div class="field__item field__item--scheduling"> <span class="field__item-wrapper"><a href="/taxonomy/term/71" hreflang="en">scheduling</a></span> </div> </div> </div> <span class="field field--name-uid field--type-entity-reference field--label-hidden"><a title="View user profile." href="/user/1" class="username">dave</a></span> <span class="field field--name-created field--type-created field--label-hidden">Tue 04/02/2020 - 09:41</span> <div class="field field-node--field-image field-name-field-image field-type-image field-label-hidden has-multiple"> <figure class="field-type-image__figure image-count-1"> <div class="field-type-image__item"> <a href="http://tech.oeru.org/sites/default/files/styles/max_1300x1300/public/2020-02/Screenshot_2020-02-11-2%20file-sample_1MB%20docx%20-%20Lane%20NextCloud.png?itok=bqhSZGni" aria-controls="colorbox" aria-label="{&quot;alt&quot;:&quot;Sample DOCX file being edited in open source OnlyOffice&quot;}" role="button" title="Sample DOCX file being edited in open source OnlyOffice" data-colorbox-gallery="gallery-field_image-eiOM02IMRxQ" class="colorbox" data-cbox-img-attrs="{&quot;alt&quot;:&quot;Sample DOCX file being edited in open source OnlyOffice&quot;}"><img src="/sites/default/files/styles/medium/public/2020-02/Screenshot_2020-02-11-2%20file-sample_1MB%20docx%20-%20Lane%20NextCloud.png?itok=OW_2e1WM" width="220" height="140" alt="Sample DOCX file being edited in open source OnlyOffice" loading="lazy" class="image-style-medium" /> </a> </div> </figure> <figure class="field-type-image__figure image-count-2"> <div class="field-type-image__item"> <a href="http://tech.oeru.org/sites/default/files/styles/max_1300x1300/public/2020-02/Screenshot_2020-02-11%20Digital%20Storage%20Weight%20and%20Volume%20xlsx%20-%20Lane%20NextCloud.png?itok=luaOg5rt" aria-controls="colorbox" aria-label="{&quot;alt&quot;:&quot;Sample XLSX file being edited in open source OnlyOffice&quot;}" role="button" title="Sample XLSX file being edited in open source OnlyOffice" data-colorbox-gallery="gallery-field_image-eiOM02IMRxQ" class="colorbox" data-cbox-img-attrs="{&quot;alt&quot;:&quot;Sample XLSX file being edited in open source OnlyOffice&quot;}"><img src="/sites/default/files/styles/medium/public/2020-02/Screenshot_2020-02-11%20Digital%20Storage%20Weight%20and%20Volume%20xlsx%20-%20Lane%20NextCloud.png?itok=CZcvoi7c" width="220" height="140" alt="Sample XLSX file being edited in open source OnlyOffice" loading="lazy" class="image-style-medium" /> </a> </div> </figure> <figure class="field-type-image__figure image-count-3"> <div class="field-type-image__item"> <a href="http://tech.oeru.org/sites/default/files/styles/max_1300x1300/public/2020-02/Screenshot_2020-02-11%20file-sample_1MB%20docx%20-%20Lane%20NextCloud.png?itok=GzQZ26uC" aria-controls="colorbox" aria-label="{&quot;alt&quot;:&quot;Another example of DOCX file being edited in open source OnlyOffice&quot;}" role="button" title="Another example of DOCX file being edited in open source OnlyOffice" data-colorbox-gallery="gallery-field_image-eiOM02IMRxQ" class="colorbox" data-cbox-img-attrs="{&quot;alt&quot;:&quot;Another example of DOCX file being edited in open source OnlyOffice&quot;}"><img src="/sites/default/files/styles/medium/public/2020-02/Screenshot_2020-02-11%20file-sample_1MB%20docx%20-%20Lane%20NextCloud.png?itok=9KcMLR4t" width="220" height="140" alt="Another example of DOCX file being edited in open source OnlyOffice" loading="lazy" class="image-style-medium" /> </a> </div> </figure> <figure class="field-type-image__figure image-count-4"> <div class="field-type-image__item"> <a href="http://tech.oeru.org/sites/default/files/styles/max_1300x1300/public/2020-02/Screenshot_2020-02-11%20Files%20-%20OERu%20NextCloud.png?itok=Zm3uP_wT" aria-controls="colorbox" aria-label="{&quot;alt&quot;:&quot;Sample of web-view of NextCloud files and folders.&quot;}" role="button" title="Sample of web-view of NextCloud files and folders." data-colorbox-gallery="gallery-field_image-eiOM02IMRxQ" class="colorbox" data-cbox-img-attrs="{&quot;alt&quot;:&quot;Sample of web-view of NextCloud files and folders.&quot;}"><img src="/sites/default/files/styles/medium/public/2020-02/Screenshot_2020-02-11%20Files%20-%20OERu%20NextCloud.png?itok=Bpnx2qg6" width="220" height="155" alt="Sample of web-view of NextCloud files and folders." loading="lazy" class="image-style-medium" /> </a> </div> </figure> <figure class="field-type-image__figure image-count-5"> <div class="field-type-image__item"> <a href="http://tech.oeru.org/sites/default/files/styles/max_1300x1300/public/2020-02/Screenshot_2020-02-11%20Polls%20-%20NZOSS%20Nextcloud.png?itok=Fp17si_J" aria-controls="colorbox" aria-label="{&quot;alt&quot;:&quot;A sample NextCloud Poll (alternative to Doodle Polls) for scheduling. Yes, it&#039;s timezone-aware!&quot;}" role="button" title="A sample NextCloud Poll (alternative to Doodle Polls) for scheduling. Yes, it&#039;s timezone-aware!" data-colorbox-gallery="gallery-field_image-eiOM02IMRxQ" class="colorbox" data-cbox-img-attrs="{&quot;alt&quot;:&quot;A sample NextCloud Poll (alternative to Doodle Polls) for scheduling. Yes, it&#039;s timezone-aware!&quot;}"><img src="/sites/default/files/styles/medium/public/2020-02/Screenshot_2020-02-11%20Polls%20-%20NZOSS%20Nextcloud.png?itok=8rpIpQne" width="220" height="154" alt="A sample NextCloud Poll (alternative to Doodle Polls) for scheduling. Yes, it&#039;s timezone-aware!" loading="lazy" class="image-style-medium" /> </a> </div> </figure> <figure class="field-type-image__figure image-count-6"> <div class="field-type-image__item"> <a href="http://tech.oeru.org/sites/default/files/styles/max_1300x1300/public/2020-02/Screenshot_2020-02-12%20ONLYOFFICE%E2%84%A2.png?itok=04xrGCN1" aria-controls="colorbox" aria-label="{&quot;alt&quot;:&quot;If your onlyoffice.domain server is working, this is what you should see in your browser!&quot;}" role="button" title="If your onlyoffice.domain server is working, this is what you should see in your browser!" data-colorbox-gallery="gallery-field_image-eiOM02IMRxQ" class="colorbox" data-cbox-img-attrs="{&quot;alt&quot;:&quot;If your onlyoffice.domain server is working, this is what you should see in your browser!&quot;}"><img src="/sites/default/files/styles/medium/public/2020-02/Screenshot_2020-02-12%20ONLYOFFICE%E2%84%A2.png?itok=1I3F7Cbi" width="220" height="187" alt="If your onlyoffice.domain server is working, this is what you should see in your browser!" loading="lazy" class="image-style-medium" /> </a> </div> </figure> <figure class="field-type-image__figure image-count-7"> <div class="field-type-image__item"> <a href="http://tech.oeru.org/sites/default/files/styles/max_1300x1300/public/2020-02/Screenshot_2020-02-13%20Apps%20-%20NZOSS%20Nextcloud.png?itok=Io3v-pzT" aria-controls="colorbox" aria-label="{&quot;alt&quot;:&quot;The NextCloud &quot;app&quot; configuration page&quot;}" role="button" title="The NextCloud &quot;app&quot; configuration page" data-colorbox-gallery="gallery-field_image-eiOM02IMRxQ" class="colorbox" data-cbox-img-attrs="{&quot;alt&quot;:&quot;The NextCloud &quot;app&quot; configuration page&quot;}"><img src="/sites/default/files/styles/medium/public/2020-02/Screenshot_2020-02-13%20Apps%20-%20NZOSS%20Nextcloud.png?itok=VGORRtXl" width="103" height="220" alt="The NextCloud &quot;app&quot; configuration page" loading="lazy" class="image-style-medium" /> </a> </div> </figure> <figure class="field-type-image__figure image-count-8"> <div class="field-type-image__item"> <a href="http://tech.oeru.org/sites/default/files/styles/max_1300x1300/public/2020-02/Screenshot_2020-02-13%20Settings%20-%20NZOSS%20Nextcloud.png?itok=8sZGBrtG" aria-controls="colorbox" aria-label="{&quot;alt&quot;:&quot;The NextCloud settings page. &quot;}" role="button" title="The NextCloud settings page. " data-colorbox-gallery="gallery-field_image-eiOM02IMRxQ" class="colorbox" data-cbox-img-attrs="{&quot;alt&quot;:&quot;The NextCloud settings page. &quot;}"><img src="/sites/default/files/styles/medium/public/2020-02/Screenshot_2020-02-13%20Settings%20-%20NZOSS%20Nextcloud.png?itok=98LUc9zv" width="220" height="163" alt="The NextCloud settings page. " loading="lazy" class="image-style-medium" /> </a> </div> </figure> <figure class="field-type-image__figure image-count-9"> <div class="field-type-image__item"> <a href="http://tech.oeru.org/sites/default/files/styles/max_1300x1300/public/2020-02/Screenshot_2020-02-13%20Settings%20-%20OnlyOffice%20-%20NZOSS%20Nextcloud_0.png?itok=KwWWWKUT" aria-controls="colorbox" aria-label="{&quot;alt&quot;:&quot;The &quot;OnlyOffice&quot; app configuration page for NextCloud&quot;}" role="button" title="The &quot;OnlyOffice&quot; app configuration page for NextCloud" data-colorbox-gallery="gallery-field_image-eiOM02IMRxQ" class="colorbox" data-cbox-img-attrs="{&quot;alt&quot;:&quot;The &quot;OnlyOffice&quot; app configuration page for NextCloud&quot;}"><img src="/sites/default/files/styles/medium/public/2020-02/Screenshot_2020-02-13%20Settings%20-%20OnlyOffice%20-%20NZOSS%20Nextcloud_0.png?itok=JdKSA022" width="220" height="189" alt="The &quot;OnlyOffice&quot; app configuration page for NextCloud" loading="lazy" class="image-style-medium" /> </a> </div> </figure> <figure class="field-type-image__figure image-count-10"> <div class="field-type-image__item"> <a href="http://tech.oeru.org/sites/default/files/styles/max_1300x1300/public/2020-02/Screenshot_2020-02-21%20App%20Bundles-%20OERu%20NextCloud.png?itok=3N1GtflH" aria-controls="colorbox" aria-label="{&quot;alt&quot;:&quot;NextCloud App Bundle configuration page.&quot;}" role="button" title="NextCloud App Bundle configuration page." data-colorbox-gallery="gallery-field_image-eiOM02IMRxQ" class="colorbox" data-cbox-img-attrs="{&quot;alt&quot;:&quot;NextCloud App Bundle configuration page.&quot;}"><img src="/sites/default/files/styles/medium/public/2020-02/Screenshot_2020-02-21%20App%20Bundles-%20OERu%20NextCloud.png?itok=c1_0PwiH" width="220" height="141" alt="NextCloud App Bundle configuration page." loading="lazy" class="image-style-medium" /> </a> </div> </figure> </div> <div class="clearfix text-formatted field field-node--body field-name-body field-type-text-with-summary field-label-hidden"> <div class="field__items"> <div class="field__item"><p><strong>Update 2023-06-14</strong>: Here's a <a href="/node/56">new tutorial for Ubuntu 22.04</a>! Consider this older tutorial obsolete (but possibly helpful for people with older systems?)</p> <p>I have previously provided an <a href="/installing-nextcloud-and-collabora-office-online-docker-ubuntu-1604">in-depth explanation about NextCloud with Collabora Office Online and how we've installed it on Ubuntu 16.04</a>. This is an update both of the process, and of the technology. NextCloud is leaping from strength to strength, and seems to be <a href="https://nextcloud.com/blog/eu-governments-choose-independence-from-us-cloud-providers-with-nextcloud/">benefiting from</a> the well-founded concern held by many in the EU about data sovereignty and the market domination (and exploitation) of US-based multinationals like Amazon, Google, Microsoft, Dropbox, and others. As a collaborative, web-based front end to LibreOffice, Collabora shows great potential... but it's not anywhere near the capabilities of Google Docs...</p> <p>The same, however, is not true of a relatively new entry into the web-based collaborative productivity application space: <a href="https://www.onlyoffice.com/">OnlyOffice</a>. The application itself (for the tech focused reader, they've built an entirely <a href="https://github.com/ONLYOFFICE/">new application ecosystem</a> primarily using modern Javascript frameworks)  is impressive in both capabilities and polish. The only real caveat I've come across is that it uses, by default, the <a href="https://openstandards.nz/case-study-microsofts-ooxml-standard">fauxpen standard formats</a> developed by Microsoft rather than the true open standard formats of <a href="https://en.wikipedia.org/wiki/OpenDocument">OpenDocumentFormat</a>. But in a world where, sadly, most people don't even know what a file format is, any software that doesn't read and write the incumbent monopolist's format with great fidelity is dead in the water.  On that count, OnlyOffice is impressive.</p> <h2>NextCloud and OnlyOffice - even better together!</h2> <p>The beauty of the open source software model is that we can connect complementary applications, like NextCloud and OnlyOffice - developed by completely separate communities - to create a tightly integrated, highly functional, diverse computing platform. This combination, along with a bunch of other NextCloud "apps", is the equal of something like Google Apps (which includes Google Docs and Google Drive), but is <em>under your control, not Google's.</em> To me, that's a crucial difference. </p> <p>With the release of NextCloud 18.0.1, NextCloud has bundled OnlyOffice with it, creating something called "<a href="https://nextcloud.com/hub/">NextCloud Hub</a>". It's pretty impressive. That's what we're setting up here!</p> <h2>Setting up your own NextCloud Hub!</h2> <p>Yes, NextCloud and OnlyOffice servers on the same host.</p> <p>If you're game to run your own (and, in my experience, it's a surprisingly well behaved system) here's how you do it.</p> <p>In preparation, you'll want to have the following ready:</p> <ul><li>a Linux virtual machine or "VM" (I recommend running the current Ubuntu LTS version, or current Debian) with an external IP address and a user with sudo privileges - <a href="/setting-your-own-bitwarden-password-keeper-and-sync-server">more info on that</a>...,</li> <li>your domain name for the NextCloud instance, pointing to the IP address of your VM,</li> <li>credentials for an email address capable of sending from a remote server (usually termed an "<a href="/configuring-linux-server-send-email-postfix-smtp-server">authenticating SMTP email account</a>")</li> </ul><p>Please note: the images accompanying this howto have been pulled from several different NextCloud and OnlyOffices I maintain.</p> <h3>Secure access with SSH</h3> <p>First things first, make sure you're logged into your host (probably via SSH) as a user who has "sudo" capabilities! You need to log into the host from your local machine. We recommend setting up <a href="https://www.digitalocean.com/community/tutorials/how-to-configure-ssh-key-based-authentication-on-a-linux-server">key-based authentication</a>.</p> <h3>Firewall with UFW</h3> <p>No computer system is ever full secure - there're always exploits waiting to be found, so security is a process of maintaining vigilance. Part of that is reducing exposure - minimising your "attack surface". Use a firewall - "<a href="https://www.digitalocean.com/community/tutorials/how-to-set-up-a-firewall-with-ufw-on-ubuntu-16-04" title="Uncomplicated FireWall">ufw</a>" is installed on Ubuntu by default. Make sure you've got exceptions for SSH (without them, you could lock yourself out of your machine! Doh!).</p> <p>Run the following commands to allow your Docker containers to talk to other services on your host.</p> <p><code>sudo ufw allow in on docker0<br /> sudo ufw allow from 172.0.0.0/8 to any</code></p> <p>Specifically for Docker's benefit, you need to tweak the default Forwarding rule (I use "vim" as my editor. If you don't know how to/want to use it, replace <strong>vim</strong> with <strong>nano</strong> everywhere you see it in the following - nano's easier to use for simple edits like this):</p> <p><code>sudo vim /etc/default/ufw</code></p> <p>and duplicate (copy and paste it) the line <code>DEFAULT_FORWARD_POLICY="DROP"</code> tweak it to look like this (commenting out the default, but leaving it there for future reference, so you know what you've changed!):</p> <p><code>#DEFAULT_FORWARD_POLICY="DROP"<br /> DEFAULT_FORWARD_POLICY="ACCEPT"</code></p> <p>You also have to edit <code>/etc/ufw/sysctl.conf</code> and remove the "#" at the start of the following lines, so they look like this:</p> <p><code>sudo vim /etc/ufw/sysctl.conf</code></p> <p><code># Uncomment this to allow this host to route packets between interfaces<br /> net/ipv4/ip_forward=1<br /> net/ipv6/conf/default/forwarding=1<br /> net/ipv6/conf/all/forwarding=1</code></p> <p>and finally restart the network stack and ufw on your server<code> </code></p> <p><code>sudo service networking restart<br /> sudo service ufw restart</code></p> <h3>Installing the Nginx webserver</h3> <p>In the configuration I'm describing here, you'll need a webserver running on the server - it'll be acting as a "proxy" for the Docker-based Nginx instance described below. I like the efficiency of Nginx and clarity of Nginx configurations over those of Apache and other open source web servers. Here's how you install it.</p> <p><code>sudo apt-get install nginx-full</code></p> <p>To allow nginx to be visible via ports 80 and 443, run</p> <p><code>sudo ufw allow "Nginx Full"</code></p> <p><strong>Note</strong>: make sure your hosting service is not blocking these ports at some outer layer (depending on who's providing that hosting service you may have to set up port forwarding).</p> <h3>Installing MariaDB</h3> <p>MariaDB is effectively a drop-in alternative to MySQL and we prefer it because it's not controlled by Oracle and has a more active developer community. On Ubuntu, MariaDB pretends to be MySQL for compatibility purposes, so don't be weirded out by the interchangeable names below. Install the server and the client like this.</p> <p><code>sudo apt-get install mariadb-server-10.0 mariadb-client-10.0</code></p> <p>You need to set a root (admin) user password - you might want to create a /root/.my.cnf file containing the following (replacing YOURPASSWORD) to let you access MariaDB without a password from the commandline<code>:</code></p> <p><code>[client]<br /> user=root<br /> password=YOURPASSWORD</code></p> <p>You should now be able to type "mysql" at the command prompt</p> <p>Tweak the configuration so that it's listening on</p> <p><code>sudo vim /etc/mysql/mariadb.conf.d/50-server.cnf </code></p> <p>and copy the bind-address line and adjust so it looks like this - we want MariaDB to be listening on all interfaces, not just localhost (127.0.0.1)...</p> <p><code># Instead of skip-networking the default is now to listen only on<br /> # localhost which is more compatible and is not less secure.<br /> #bind-address           = 127.0.0.1<br /> bind-address            = 0.0.0.0</code></p> <p>Then restart MariaDB:</p> <p><code>sudo service mysql restart</code></p> <p>It should now be listening on port 3306 on all interfaces, i.e. 0.0.0.0.</p> <p>Now set up the database which will hold NextCloud's data. Log into the MySQL client on the host (if you've created a .my.cnf file in your home directory as describe above, you won't need to enter your username and password):</p> <p><code>mysql -u root -p</code></p> <p>Enter your root password when prompted. It's also a good idea to gin up a password for your "nextcloud" database user. I usually use pwgen (<code>sudo apt-get install pwgen</code>) - for example running this command will give you a single 19 character password without special characters (just numbers and letters):</p> <p><code>pwgen -s 19 1</code></p> <p>Giving you something like this (but if it's truly random, almost <em>certainly not exactly </em>this):</p> <p>bYIOSrvR9aGwL5FRGFU</p> <p>At the prompt (which will look something like <code>MariaDB [(none)]&gt;</code>) enter the following lines (putting your password in place of [passwd]):</p> <p><code>CREATE DATABASE nextcloud CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;<br /> CREATE USER "nextcloud"@"%" IDENTIFIED BY "[passwd]";<br /> GRANT ALL ON nextcloud.* to "nextcloud"@"%";<br /> FLUSH PRIVILEGES;</code></p> <p>Then enter \q to exit.</p> <h2>Prepare your Docker Compose host</h2> <p>We make use of the NextCloud community's <a href="https://hub.docker.com/_/nextcloud/" title="Documentation for the reference NextCloud Docker container.">stable Docker container</a> which they keep up to date. Similarly, the OnlyOffice developers maintain a Docker container, too. We will run them both on this same server as separate services via <a href="https://docs.docker.com/compose/">Docker Compose</a>. The two sets of Docker containers will look like this:</p> <ol><li>a suite of NextCloud containers: <ol><li>the main PHP-FPM container (which provides most of the functionality for NextCloud using the PHP scripting engine,</li> <li>an identical container to the PHP one which runs the cron service (which does periodic administrative tasks relevant to NextCloud)</li> <li>a Redis container (which provides performance improving caching for NextCloud), and</li> <li>an Nginx webserver container which makes it easier to manage the configuration and paths of the NextCloud instance. It means that on the hosting server, we only need to run a proxying web server, which is easy.</li> </ol></li> <li>the single OnlyOffice container which, despite the Docker convention of each container running only a single services, runs the whole OnlyOffice stack, which includes PostgreSQL, Nginx, Rabbit-MQ, Python, and NodeJS.</li> </ol><p>The way I prefer to implement this set of containers is to use:</p> <p><code>sudo apt-get install docker-compose </code></p> <p>to set up the entire Docker and Docker Compose system on your server.</p> <p>Then set up a place for your Docker containers (replace "me" with your non-root username on the server) and the associated persistent data (your Docker containers should hold <em>no</em> important data - you should be able to delete and recreate them entirely without losing any important data or configuration):</p> <p><code>sudo mkdir /home/data</code><br /><code>sudo mkdir /home/data/nextcloud<br /> sudo mkdir /home/data/nextcloud-nginx<br /> sudo mkdir /home/data/nextcloud-redis</code><br /><code>sudo mkdir /home/data/onlyoffice</code><br /><code>sudo mkdir /home/docker<br /> sudo mkdir /home/docker/nextcloud</code><br /><code>sudo chown -R me:me /home/docker</code></p> <h2>NextCloud Install</h2> <p>First, let's set up NextCloud (this also installs the OnlyOffice server):</p> <p><code>cd /home/docker/nextcloud</code></p> <p>Here's an example of the required docker-compose.yml file (you can create this via a text editor like "nano" which should be pre-installed on any VM these days (or use my preferred, but less intuitive, editor, vim) <code>nano docker-compose.yml</code> in the /home/docker/nextcloud directory):</p> <p><code>version: '3'<br /> services:<br />   nginx:<br />     container_name: nginx-server<br />     image: nginx<br />     ports:<br />       - 127.0.0.1:8082:80<br />     volumes:<br />       - /home/data/nextcloud-nginx/nginx/nginx.conf:/etc/nginx/nginx.conf:ro<br />       - /home/data/nextcloud:/var/www/html<br />     links:<br />       - app<br />     environment:<br />       - VIRTUAL_HOST<br />     restart: unless-stopped      <br />   app:<br />     container_name: app-server<br />     image: nextcloud:fpm<br />     stdin_open: true<br />     tty: true<br />     links:<br />       - redis<br />     expose:<br />       - '80'<br />       - '9000'<br />     volumes:<br />       - /home/data/nextcloud:/var/www/html<br />     restart: unless-stopped      <br />   cron:<br />     image: nextcloud:fpm<br />     volumes:<br />       - /home/data/nextcloud:/var/www/html<br />     user: www-data<br />     entrypoint: |<br />       bash -c 'bash -s &lt;&lt;EOF<br />       trap "break;exit" SIGHUP SIGINT SIGTERM<br />       while /bin/true; do<br />         /usr/local/bin/php /var/www/html/cron.php<br />         sleep 900<br />       done<br />       EOF'<br />     restart: unless-stopped      <br />   redis:<br />     image: redis:alpine<br />     volumes:<br />       - /home/data/nextcloud-redis:/data<br />     restart: unless-stopped<br />   onlyoffice-document-server:<br />     container_name: onlyoffice-document-server<br />     image: onlyoffice/documentserver:latest<br />     stdin_open: true<br />     tty: true<br />     restart: unless-stopped<br />     expose:<br />       - '80'<br />       - '443'<br />     volumes:<br />       - /home/data/onlyoffice/data:/var/www/onlyoffice/Data<br />       - /home/data/onlyoffice/log:/var/log/onlyoffice</code></p> <p>The "port" specified above, 8082 for <code>nginx</code> is arbitrary - I picked it to ensure it doesn't don't conflict with ports being used by other containers on my server - you can use these if you want, or use <code>sudo netstat -punta</code> to see what ports are currently claimed by other services on your server (if there are any) and pick one that doesn't clash! If it scroll past too fast, you can pipe it into less to allow you to scroll and search like this: <code>sudo netstat -punta | less</code> - hit "q" to exit or "/" to initiate a text search.</p> <p>You will also need to provide the "nginx.conf" file referenced in the nginx section of the file. Do that by using your editor, e.g. <code>nano nginx.conf</code>, and enter this content (you shouldn't need to alter anything):</p> <p><code>user  www-data;</code></p> <p><code>worker_processes  1;</code></p> <p><code>error_log  /var/log/nginx/error.log warn;<br /> pid        /var/run/nginx.pid;</code></p> <p><code>events {<br />     worker_connections  1024;<br /> }</code></p> <p><code>http {<br />     upstream backend {<br />         server app-server:9000;<br />     }</code></p> <p><code>    include       /etc/nginx/mime.types;<br />     default_type  application/octet-stream;</code></p> <p><code>    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '<br />                       '$status $body_bytes_sent "$http_referer" '<br />                       '"$http_user_agent" "$http_x_forwarded_for"';</code></p> <p><code>    access_log  /var/log/nginx/access.log  main;</code></p> <p><code>    sendfile        on;<br />     #tcp_nopush     on;</code></p> <p><code>    keepalive_timeout  65;</code></p> <p><code>    map $http_host $this_host {<br />         "" $host;<br />         default $http_host;<br />     }</code></p> <p><code>    map $http_x_forwarded_proto $the_scheme {<br />         default $http_x_forwarded_proto;<br />         "" $scheme;<br />     }</code></p> <p><code>    map $http_x_forwarded_host $the_host {<br />         default $http_x_forwarded_host;<br />         "" $this_host;<br />     }</code></p> <p><code>    server {<br />         listen 80;</code></p> <p><code>        # Add headers to serve security related headers<br />         add_header Strict-Transport-Security "max-age=15768000; includeSubDomains; preload;";<br />         add_header X-Content-Type-Options nosniff;<br />         add_header X-XSS-Protection "1; mode=block";<br />         add_header X-Robots-Tag none;<br />         add_header X-Download-Options noopen;<br />         add_header X-Permitted-Cross-Domain-Policies none;</code></p> <p><code>        root /var/www/html;<br />         client_max_body_size 10G; # 0=unlimited - set max upload size<br />         fastcgi_buffers 64 4K;</code></p> <p><code>        gzip off;</code></p> <p><code>        index index.php;<br />         error_page 403 /core/templates/403.php;<br />         error_page 404 /core/templates/404.php;</code></p> <p><code>        rewrite ^/.well-known/carddav /remote.php/dav/ permanent;<br />         rewrite ^/.well-known/caldav /remote.php/dav/ permanent;</code></p> <p><code>        location = /robots.txt {<br />             allow all;<br />             log_not_found off;<br />             access_log off;<br />         }</code></p> <p><code>        location ~ ^/(build|tests|config|lib|3rdparty|templates|data)/ {<br />             deny all;<br />         }</code></p> <p><code>        location ~ ^/(?:\.|autotest|occ|issue|indie|db_|console) {<br />             deny all;<br />         }</code></p> <p><code>        location / {<br />             rewrite ^/remote/(.*) /remote.php last;<br />             rewrite ^(/core/doc/[^\/]+/)$ $1/index.html;<br />             try_files $uri $uri/ =404;<br />         }</code></p> <p><code>        location ~* ^/ds-vpath/ {<br />             rewrite /ds-vpath/(.*) /$1  break;<br />             proxy_pass http://onlyoffice-document-server;<br />             proxy_redirect     off;</code></p> <p><code>            client_max_body_size 100m;</code></p> <p><code>            proxy_http_version 1.1;<br />             proxy_set_header Upgrade $http_upgrade;<br />             proxy_set_header Connection "upgrade";</code></p> <p><code>            proxy_set_header Host $http_host;<br />             proxy_set_header X-Real-IP $remote_addr;<br />             proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;<br />             proxy_set_header X-Forwarded-Host $the_host/ds-vpath;<br />             proxy_set_header X-Forwarded-Proto $the_scheme;<br />             #proxy_set_header X-Forwarded-Proto 'https';<br />         }</code></p> <p><code>        location ~ \.php(?:$|/) {<br />             fastcgi_split_path_info ^(.+\.php)(/.+)$;<br />             include fastcgi_params;<br />             fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;<br />             fastcgi_param PATH_INFO $fastcgi_path_info;<br />             fastcgi_param HTTPS off;<br />             fastcgi_param modHeadersAvailable true; #Avoid sending the security headers twice<br />             fastcgi_pass backend;<br />             fastcgi_intercept_errors on;<br />         }</code></p> <p><code>        # Adding the cache control header for js and css files<br />         # Make sure it is BELOW the location ~ \.php(?:$|/) { block<br />         location ~* \.(?:css|js)$ {<br />             add_header Cache-Control "public, max-age=7200";<br />             # Add headers to serve security related headers<br />             add_header Strict-Transport-Security "max-age=15768000; includeSubDomains; preload;";<br />             add_header X-Content-Type-Options nosniff;<br />             add_header X-Frame-Options "SAMEORIGIN";<br />             add_header X-XSS-Protection "1; mode=block";<br />             add_header X-Robots-Tag none;<br />             add_header X-Download-Options noopen;<br />             add_header X-Permitted-Cross-Domain-Policies none;<br />             # Optional: Don't log access to assets<br />             access_log off;<br />         }</code></p> <p><code>        # Optional: Don't log access to other assets<br />         location ~* \.(?:jpg|jpeg|gif|bmp|ico|png|swf)$ {<br />             access_log off;<br />         }</code><br /><code>    }<br /> }</code></p> <p>That should be all the configuration you need to make the Docker containers go.</p> <h2>Configuring Nginx to proxy NextCloud and OnlyOffice</h2> <p>The next step is configuring the local nginx proxy servers for NextCloud and OnlyOffice using the nginx instance you installed earlier. That's what responds to the domain name you choose for this service. In our case, the name is <a href="https://docs.oeru.org">https://docs.oeru.org</a> - you can have a look at it to see what you should be seeing when you first start things up! We use <a href="https://letsencrypt.org" title="This is an incredible free and open source service, that is single-handedly making the web a much safer place.">Let's Encrypt</a> to provide secure hosting - <a href="/protecting-your-users-lets-encrypt-ssl-certs">here're my Let's Encrypt instructions</a> on setting it up. The key thing to realise is that your "certificates" need to exist for Nginx to restart with the new configurations below - use the "commenting out the intervening lines" trick mentioned in my instructions to bootstrap the creation of your secure certificates!</p> <p>To configure the proxy, you need to create this configuration file in your /etc/nginx/sites-available/ directory.</p> <h3>NextCloud Proxy Configuration</h3> <p>Create a file with a meaningful name for your NextCloud Proxy, perhaps based on the domain name you've chosen (our file for docs.oeru.org is called "docs") using the same editing approach as the last few (although this is in a different directory) for example <code>sudo nano /etc/nginx/sites-available/nextcloud</code> with the following contents, replacing <code>[nextcloud.domain]</code> with your selected domain name, but leave off the [ ] (those are just there to make sure nginx errors if you've missed replacing any) - and the port number 8082 if you've opted to change to a different one!:</p> <p><code>server {<br />     listen 80;<br />     listen [::]:80;<br />     server_name <strong>[nextcloud.domain]</strong>;</code></p> <p><code>    include includes/letsencrypt.conf;</code></p> <p><code>    # enforce https<br />     location / {<br />         return 302 https://$server_name$request_uri;<br />     }<br /> }</code></p> <p><code>server {<br />     listen 443 ssl;<br />     listen [::]:443 ssl;<br />     #listen 127.0.0.1:443 ssl;</code></p> <p><code>    server_name <strong>[nextcloud.domain]</strong>;</code></p> <p><code>    ## Access and error logs.<br />     access_log /var/log/nginx/<strong>[nextcloud.domain]</strong>_access.log;<br />     error_log /var/log/nginx/<strong>[nextcloud.domain]</strong>_error.log;</code></p> <p><code>    ssl_certificate /etc/letsencrypt/live/<strong>[nextcloud.domain]</strong>/fullchain.pem;<br />     ssl_certificate_key /etc/letsencrypt/live/<strong>[nextcloud.domain]</strong>/privkey.pem;</code></p> <p><code>    ssl on;<br />     # from http://axiacore.com/blog/enable-perfect-forward-secrecy-nginx/<br />     ssl_session_cache shared:SSL:10m;<br />     ssl_session_timeout  10m;<br />     # limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s;<br />     # forward secrecy settings<br />     ssl_protocols TLSv1 TLSv1.1 TLSv1.2;<br />     ssl_prefer_server_ciphers on;<br />     ssl_ciphers "EECDH+ECDSA+AESGCM EECDH+aRSA+AESGCM EECDH+ECDSA+SHA384 EECDH+ECDSA+SHA256 EECDH+aRSA+SHA384 EECDH+aRSA+SHA256 EECDH+aRSA+RC4 EECDH EDH+aRSA RC4 !aNULL !eNULL !LOW !3DES !MD5 !EXP !PSK !SRP !DSS !RC4";<br />     ssl_dhparam /etc/ssl/certs/dhparam.pem;</code></p> <p><code>    #location = /robots.txt {<br />     #    allow all;<br />     #    log_not_found off;<br />     #    access_log off;<br />     #}</code></p> <p><code>    # The following 2 rules are only needed for the user_webfinger app.<br />     # Uncomment it if you're planning to use this app.<br />     rewrite ^/.well-known/host-meta /public.php?service=host-meta last;<br />     rewrite ^/.well-known/host-meta.json /public.php?service=host-meta-json last;</code></p> <p><code>    # The following rule is only needed for the Social app.<br />     # Uncomment it if you're planning to use this app.<br />     rewrite ^/.well-known/webfinger /public.php?service=webfinger last;</code></p> <p><code>    location ^~ / {<br />         proxy_pass http://127.0.0.1:<strong>8082</strong>;<br />         proxy_set_header Upgrade $http_upgrade;<br />         proxy_set_header Connection "Upgrade";<br />         proxy_set_header Host $http_host;<br />         proxy_read_timeout 36000s;<br />         proxy_buffering off;<br />         proxy_max_temp_file_size 15000m;<br />     }<br />     client_max_body_size 1G;<br />     fastcgi_buffers 64 4K;<br />     add_header Strict-Transport-Security "max-age=31536000; includeSubdomains;";<br />     # Remove X-Powered-By, which is an information leak<br />     fastcgi_hide_header X-Powered-By;<br /> }</code></p> <p>Note: you'll need to create the file cited in the proxy configration: <code>/etc/ssl/certs/dhparam.pem </code></p> <p>You can do this as follows (install the necessary software, backup any possible existing version as a matter of prudence, and create a new one):</p> <p><code>sudo apt update &amp;&amp; sudo apt install openssl<br /><span class="pun">sudo [<span class="pln"> </span>-</span><span class="pln">f </span><span class="str">"</span>/etc/ssl/certs/dhparam.pem<span class="str">"</span><span class="pln"> </span><span class="pun">]</span><span class="pln"> </span><span class="pun">&amp;&amp;</span><span class="pln"> sudo mv </span>/etc/ssl/certs/dhparam.pem /etc/ssl/certs/dhparam.pem</code>.bak<br /><span style="font-family:monospace"><span style="color:#000000;background-color:#ffffff;">sudo openssl dhparam -out /etc/ssl/certs/dhparam.pem 2048</span></span><br />  </p> <p>Once those are created, you have to make sure that they're "enabled" (replacing with your file names, of course):</p> <p><code>sudo cd /etc/nginx/sites-enabled<br /> sudo ln -sf ../sites-available/nextcloud .</code></p> <p>To confirm that there aren't any typos or issues that might make nginx unhappy, run</p> <p><code>sudo nginx -t</code></p> <p>If all's well, get nginx to reread its configuration with the new files (if not, it might be because you missed replacing one of the [tokens]):</p> <p><code>sudo service nginx reload</code></p> <h2>Firing up your NextCloud!</h2> <p>Phew - congratulations on getting here! We've reached the moment of truth where we need to see if this whole thing will work!</p> <p>We need to make sure we're back in the NextCloud Docker directory we set up:</p> <p><code>cd /home/docker/nextcloud</code></p> <p>and then we need to try running our docker-compose script to "pull" in the pre-built Docker containers we've specified in our docker-compose.yml file:</p> <p><code>docker-compose pull</code></p> <p>All going well, after a few minutes (longer or shorter depending on the speed of your server's connection) you should have download the Nginx, Redis, and NextCloud Docker images. Then you can run:</p> <p><code>docker-compose up -d &amp;&amp; docker-compose logs -f</code></p> <p>This will attempt to start up the containers (bringing them "up" in daemon mode, thus the -d) and then show you a stream of log messages from the containers, preceded by the container name. This should help you debug any problems that occur during the process (ideally, none).</p> <p>Once you see log messages streaming past, and no obvious "container exited" or other error messages (which will usually contain the word "error" a lot), you should be able to point your browser at your selected domain name and bring it up in your browser! Just point your web browser at <code>https://nextcloud.domain</code> (replacing with your domain, of course - the https assumes you've got your Let's Encrypt certificate set up - I recommend doing that first).</p> <h3>Configuring database access</h3> <p>On doing so, if all is well, you should be directed through the database set up process for your NextCloud instance. Your details should be:</p> <p>database IP: 172.17.0.1 - this is the default IP of the Docker host server.<br /> database name: nextcloud<br /> database user: nextcloud<br /> database password: (the one you came up with above)</p> <h3>Configuring the Admin user</h3> <p>Once that's set and working, NextCloud will install all the relevant database tables and initial data. You'll be asked to set up an <em>admin user</em> account, which can be "admin" (you could make it something different to help stymie nefarious probes that assume you've got a user called "admin" - but don't forget what you've called it!) and some strong password you create (you can use the pwgen utility you used earlier) - I'd recommend recording it somewhere. I would <em>not</em> recommend making your own account, in your name, the main admin account. Instead, I recommend creating a second account, <em>with administrator privileges</em>, for yourself, but leave the admin account purely for administrative activities.</p> <h3>Configuring Outgoing Email</h3> <p>To allow your NextCloud instance to send outgoing email, so that your site can alert you to security updates that need to be applied, or so that users can request a replacement password if they've forgot theirs, you'll need an <em>authenticating SMTP account</em> somewhere. Most of you already have one. You'll probably want to set up a dedicated email address for this server somewhere, perhaps something like "<a href="mailto:nextcloud@your.domain">nextcloud@your.domain</a>" or similar, with a username (often just the email address) and a password. You'll need the following details:</p> <p>SMTP server : an IP address or a domain name<br /> SMTP username: a username or an email address<br /> SMTP password: a strong password already configured for the username on that server<br /> SMTP login security: whether login is via TLS, SSL, or unsecure (!!), and<br /> SMTP login method: plain, encrypted, "login" or some other value.</p> <p>You should be able to test your email settings to make sure the details you've entered are valid. If you need to adjust these settings later, you can go to the admin menu (top right of the web browser interface) and go to Admin-&gt;Additional Settings  - should have a path of <code>https://nextcloud.domain/settings/admin/additional</code></p> <h2>Setting up OnlyOffice</h2> <p>The OnlyOffice server should already be running - if you point your browser at <code>https://nextcloud.domain/ds-vpath/</code> you should see something like the "Document Server is running" (with a big green "tick") page included in the images accompanying this article.</p> <h3>Configuring OnlyOffice Integration with NextCloud</h3> <p>Once you're logged in to NextCloud as your own user, looking at your own default folders, you can start having a look around. You should have an "admin" menu (assuming you've created your user with Administrator privileges) at the top right of the web interface. If you go to Apps, you can install the new "Hub bundle" available under the "App bundles" option (see attached image). If you don't want the whole bundle you can just use the search box to search for "OnlyOffice" or go to the "Office &amp; text" App category and enable the OnlyOffice "official" app, at which point it will automatically download the latest version of the connector app and install it (it should appear in your /home/data/nextcloud/apps directory)</p> <p>Once you've done that, go to your top right menu again, selecting Admin, and you should see "OnlyOffice" as an option in the left column (which starts with "Basic settings"). Selecting that, you'll need to enter the following:</p> <ul><li> "Document Editing Service address":<code> /ds-vpath/</code></li> <li><code>"</code>Secret key": (leave blank)</li> <li> Under "Advanced server settings" <ul><li> <p class="onlyoffice-header">"Document Editing Service address for internal requests from the server": <code>http://onlyoffice-document-server/</code></p> </li> <li> <p class="onlyoffice-header">"Server address for internal requests from the Document Editing Service": <code>http://nginx-server/</code></p> </li> </ul></li> </ul><p>When you're done, click "Save".</p> <p>You can also select formats you'd like OnlyOffice to open and edit files of those types are clicked or created. I've selected the following: doc, docx, odp, ods, odt, ppt, pptx, xls, xlsx, and in the second section: csv and txt.</p> <p>You can also make other editor customisations as you desire. The only Editor customisation setting I <em>haven't</em> selected is "Display Chat menu button" because NextCloud Hub provides an integrated Chat service, making this one within OnlyOffice an unnecessary distraction.</p> <p>Once finished configuring, you should have the ability to go back to the home of your NextCloud install, which should show you your top-level folders. If you click the "+" next to the home icon (top left of the folder pane) you should now have the option to create (in addition to "Upload file", "New folder", "New text file") a "New Document", "New Spreadsheet", and "New Presentation". Clicking those should give you the OnlyOffice interface for the designated content type.</p> <p>Similarly, you can use the "Upload file" to upload a document in a format that is supported by OnlyOffice. Once uploaded, clicking on the filename should open it for editing in the appropriate OnlyOffice interface.</p> <p>It is saved as it is changed, so you shouldn't need to save it explicitly.</p> <h2>Keeping the whole thing up-to-date</h2> <p>So, as you're no doubt aware, both NextCloud and OnlyOffice are always being improved and updated. I certainly encourage you to keep your installations up-to-date.</p> <p>While you'll periodically be alerted that NextCloud <strong>apps</strong> have available updates (these can be upgraded through the browser interface) updates to the NextCloud and OnlyOffice systems themselves need to be undertaken by upgrading their containers. Luckily it's easy to do (although I strongly urge you to ensure you have a very recent backup of both database and uploaded files - they're the files in /home/data/nextcloud/data and /home/data/onlyoffice/ (note, backups of OnlyOffice are complicated somewhat by the fact that you can't reliably back up running PostgreSQL instance simply by backing up its files - see a solution below):</p> <p>Updating the container should be as easy as either doing another</p> <p><code>docker-compose pull </code></p> <p>and then shutting down Docker container via a</p> <p><code>docker-compose up -d</code></p> <p>which will remove any old containers (this won't remove any data you want to save if you followed the directions above! But remember to do it in the right directory!) and start up the new versions you've just pulled.</p> <p>Use <code>docker-compose logs -f</code> to watch the logs - you'll likely see useful debugging information in the unlikely event that something goes wrong in the upgrade process.</p> <h2>Backing up NextCloud</h2> <p>To back up your instance on your server, you need two things: a file system backup of your /home/data/nextcloud directory, and database dumps of your database.</p> <p>There're lots of ways to back up your files (I've recently updated to using a system called Restic to make off-server incremental encrypted backups - I plan to document this in a future howto! - although there're <a href="https://www.howtoforge.com/linux_rdiff_backup">other documented approaches</a> - leave a comment below if you'd like to learn more about my approach!).</p> <p>Backing up your MariaDB databases is as easy installing automysqlbackups:</p> <p><code>sudo apt install automysqlbackups</code></p> <p>You'll find daily versioned dumps of your MariaDB database(s) in /var/lib/automysqlbackups on your VM host's filesystem. To run an ad hoc backup (which will replace the previous backup from that day, if there is one) just run</p> <p><code>sudo automysqlbackups</code></p> <h2>Backup OnlyOffice</h2> <p>Along with backing up the files in your /home/data/onlyoffice directory, you'll also want a proper "dump" of your PostgreSQL backup (you can write simple bash scripts to do this regularly, automatically), particularly prior to doing an upgrade (to allow for recovery if something goes badly wrong, which is always possible). You can achieve this by going to</p> <p><code>cd /home/docker/onlyoffice</code></p> <p>and running this</p> <p><code>DATE=`date +%Y%m%d` &amp;&amp; FILE=/home/data/onlyoffice/backup/fullbackup-${DATE}.sql &amp;&amp; docker-compose exec onlyoffice sudo -u postgres pg_dumpall &gt; ${FILE} &amp;&amp; gzip ${FILE}</code></p> <p>which will assign the current date to DATE, the relevant filename to FILE, and then put the backup SQL into a dated file called $FILE and compress the result with gzip :)</p> <p>At some point, I'll modify my normal versioned dated database backup scripts to cater for this solution and make the result available on <a href="https://git.oeru.org">https://git.oeru.org</a> - in the meantime, you can use the above before you do a backup and manually delete older backups if they start taking up too much space (or, better still, write your own clever script that does it automatically and let me know about it!).</p> </div> </div> </div> <section class="field field-node--field-blog-comments field-name-field-blog-comments field-type-comment field-label-above comment-wrapper"> <a name="comments"></a> <div class="comment-form-wrapper"> <h2 class="comment-form__title">Add new comment</h2> <drupal-render-placeholder callback="comment.lazy_builders:renderForm" arguments="0=node&amp;1=29&amp;2=field_blog_comments&amp;3=comment" token="9kYJqJN_nL4QNtjWT8YsPb_jXY2Bv9NrASHDdb5feiU"></drupal-render-placeholder> </div> </section> Mon, 03 Feb 2020 20:41:16 +0000 dave 29 at http://tech.oeru.org