18.04 http://tech.oeru.org/ en Configuring a Linux server to send email via the Postfix SMTP server using an external authenticating SMTP host http://tech.oeru.org/configuring-linux-server-send-email-postfix-smtp-server-using-external-authenticating-smtp-host <span class="field field--name-title field--type-string field--label-hidden">Configuring a Linux server to send email via the Postfix SMTP server using an external authenticating SMTP host</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--postfix"> <span class="field__item-wrapper"><a href="/taxonomy/term/66" hreflang="en">postfix</a></span> </div> <div class="field__item field__item--smtp"> <span class="field__item-wrapper"><a href="/taxonomy/term/67" hreflang="en">smtp</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--free--open-source"> <span class="field__item-wrapper"><a href="/taxonomy/term/6" hreflang="en">free &amp; open source</a></span> </div> <div class="field__item field__item--foss"> <span class="field__item-wrapper"><a href="/taxonomy/term/10" hreflang="en">foss</a></span> </div> <div class="field__item field__item--_004"> <span class="field__item-wrapper"><a href="/taxonomy/term/75" hreflang="en">20.04</a></span> </div> <div class="field__item field__item--_204"> <span class="field__item-wrapper"><a href="/taxonomy/term/85" hreflang="en">22.04</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" lang="" about="/user/1" typeof="schema:Person" property="schema:name" datatype="" class="username">dave</a></span> <span class="field field--name-created field--type-created field--label-hidden">Mon 02/08/2021 - 14:08</span> <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>Just about any and every server needs to be able to send email - whether it's end-user-email, like password recovery services for a website to emails to system administrators reporting on the status of system backups and errors. The problem is that it's <em>non trivial</em> (understatement) to set up a mail server properly.</p> <p>This howto assumes you have a Linux server (these instructions are for Ubuntu 22.04 and 20.04, although it should work on earlier versions of Ubuntu server and Debian Linux with minor changes, and the concepts will be very similar on other Linuxen) with a static IP address, with one or more fully-qualified-domain-names (fdqn) pointing at that address, and you have SSH-based access to it. I've <a href="/setting-your-own-bitwarden-password-keeper-and-sync-server">previously provided tips</a> on how to get to this stage.</p> <h2>Authenticating SMTP</h2> <p>To send email, you need access to a server, somewhere on the Internet, that provides the <a href="https://en.wikipedia.org/wiki/Simple_Mail_Transfer_Protocol">Simple Mail Transfer Protocol</a> (SMTP) service. It's an open standard, and for most of the history of the Internet, email services have been mostly provided by Free and Open Source Software (FOSS) tools - the first SMTP was called "<a href="https://en.wikipedia.org/wiki/Sendmail">Sendmail</a>" and it was fully FOSS, and it's still in use today (although it has mostly been superseded by faster, more secure systems, the best of which are also FOSS).</p> <p>At the OERu, we use the <a href="https://mailcow.github.io/mailcow-dockerized-docs/" title="Dockerised MailCow">Docker-based installation of the amazing, completely FOSS MailCow project</a> to provide our organisational email services. I might cover that set up in a future tutorial here, because MailCow makes an otherwise almost intractable problem - hosting your own email service - much more tractable. Having a MailCow set up means we can offer "full service" email for any number of domains and users and aliases with all the bells and whistles including incoming and outgoing mail with all the virus scanning (we don't really need it because we use Linux desktops, but for other folks it's useful) and dynamic spam filtering services you'd expect from a much larger operation: <a href="https://mailcow.email/">Team MailCow</a> have done an amazing job in pulling together a comprehensive set of FOSS applications to provide all the conceivable requirements of a full-fledged, multi-domain email system, including shared calendaring, contacts, and webmail. A great companion to your organisation's MailCow server would be a <a href="/setting-your-own-bitwarden-password-keeper-and-sync-server">BitWarden password safe</a> server (also FOSS)... just sayin'.</p> <p>So, now, assuming that we have a MailCow server or some other functionally equivalent SMTP service available (apparently you can <a href="https://support.google.com/a/answer/2956491">do this with Gmail</a>, if you're a paying using although because of Google's terms of use, we recommend finding a more trustworthy solution), we have the option of "authenticated SMTP" for outgoing email using credentials we can set up. For example, in MailCow, we can specify a domain we host, like say <strong>oeru.org</strong> (and for which we've defined an MX record and a few other relevant records as guided by MailCow administrative web interface). On top of that, we can specify a mailbox for a dedicated "send stuff from remote relay hosts" email address using that domain, like <strong><a href="mailto:smtp@oeru.org">smtp@oeru.org</a></strong>, with a strong password. With that, we can <em>securely </em>send email using that email address as the username and that password from <em>anywhere we have access to the Internet</em>.</p> <p>The <strong>only tricky part</strong> is that we have to ensure that whatever "reply to" email address we specify from our applications, say <strong><a href="mailto:notifications@tech.oeru.org">notifications@tech.oeru.org</a></strong>, is using a domain we <em>also host on the same server, </em>and that there's an <em>email alias</em> of that email address defined and set as "allow to send from <a href="mailto:smtp@oeru.org">smtp@oeru.org</a>" in the MailCow interface. If we haven't made sure of that, our mail server is likely to reject sending emails with that "mismatching" email address. This is a basic spam deterrence measure, which is for the best, despite sometimes making a email system administrator's life harder.</p> <p>Once we've got that (and it's easy once you've done it once or twice - I'm mostly writing this down now so I don't have to try to re-remember every time I need to set up a new server - and I hope it helps others, too), we can set up any server we control to send secure (and spam-filter-resilient) email. For what it's worth, too, MailCow uses Postfix as its SMTP server component (there're a bunch of other components, too).</p> <h2>Postfix SMTP with SmartHost</h2> <p>The first thing you need to do to create a postfix <a href="https://en.wikipedia.org/wiki/Smart_host">smarthost</a> is to install the postfix application on a new server (this assumes you're logged in with a user who has "sudo" - aka admin - permissions):</p> <p><code>sudo apt update &amp;&amp; sudo apt install postfix bsd-mailx</code></p> <p>During the install, you'll be asked to select a bunch of configuration parameters. Select the defaults except:</p> <ul><li>Select "Internet Site with Smarthost",</li> <li>fill in the domain name for your server,</li> <li>the domain name and port (in the form <code>[smtp server domain]:[port]</code>, e.g. <code>smtp.oeru.org:587</code> ) of your "smarthost" who'll be doing the authenticating SMTP for you, and</li> <li>the email address to which you want to receive system-related messages.</li> </ul><p>After that's done, you can proceed.</p> <h2>Next Steps</h2> <p>For the rest of this tutorial, you'll need to do the following. First, select your text editor. I use vim, but if you're new to the command line, I recommend using nano - it's more straightforward:</p> <p><code>EDIT=`which nano`</code> or <code>EDIT=`which vim`</code></p> <p><code>sudo $EDIT /etc/aliases</code></p> <p>We need to make sure the "root" user points to a real email address. Add a line at the bottom which says (replacing [your email] with <em>your email :) </em>)</p> <p><code>root: [your email]</code></p> <p>After which you'll need to convert the aliases file into a form that postfix can process, simply by running this:</p> <p><code>sudo newaliases</code></p> <p>Then we have to define the authentication credentials required to convince your mail server that you're you!</p> <p><code>sudo $EDIT /etc/postfix/relay_password</code></p> <p>The resulting file only needs one line with three bits of information:</p> <p><code>[smtp server domain] [user name]:[password]</code></p> <p>for example:</p> <p><code>smtp.oeru.org smtp@oeru.org:SomeObscurePassw0rd</code></p> <p>Then save the file and, like the aliases file, run the conversion process (which uses a slightly different mechanism):</p> <p><code>sudo postmap /etc/postfix/relay_password</code></p> <p>Finally, we'll edit the main configuration file for Postfix to tell it about all this stuff:</p> <p><code>sudo $EDIT /etc/postfix/main.cf</code></p> <p>If your SMTP server uses port 25 (the default for <em>unencrypted</em> SMTP) you don't have to change anything, although most people nowadays prefer to use StartTLS or otherwise encrypted transport to at least ensure that your SMTP authentication details (<em>at least</em>) are transferred encrypted. That means using port 587 or 465. If you're using either of those ports, find the "relayhost = [your server name]" line... and add your port number after a colon, like this</p> <p><code>relayhost = [your server name]:[server port] </code></p> <p>or, for example:</p> <p><code>relayhost = smtp.oeru.org:465 </code></p> <p>Next, add the following lines at the bottom of the file:</p> <p><code># added to configure accessing the relay host via authenticating SMTP<br /> smtp_sasl_auth_enable = yes<br /> smtp_sasl_password_maps = hash:/etc/postfix/relay_password<br /> smtp_sasl_security_options = noanonymous</code><br /><code>smtp_tls_security_level = encrypt</code></p> <p><code># if you're using Ubuntu prior to 20.04, uncomment (remove the #) the </code><br /><code># earlier line smtp_tls_security_level = may to save errors in 'postfix check'<br /> # and comment this line (by adding a # at the start)<br /> smtp_tls_wrappermode = yes</code></p> <p>And, finally, comment out the line <code>smtp_tls_security_level = may</code> higher in the file - careful not to confuse it with the very similar <code>smtpd_tls_security_level</code> variable (note the extra '''d''' in `smtpd...`) line.</p> <p>Save the file, and then check that your syntax is correct:</p> <p><code>sudo postfix check</code></p> <p>If it is (running the command returns no errors, and it might not return anything at all - that's a good thing!), then you can run</p> <p><code>sudo postfix reload</code></p> <p>to get postfix to reload its configurations and you can test out your new smarthost-configured SMTP server!</p> <p>If not, the output of the check command will usually give you a helpful insight into what is wrong with your configuration... you'll also find that looking at the mail log is very helpful and offers great insights:</p> <p><code>sudo less +G /var/log/mail.log</code></p> <p>and if you're not able to fix it based on those, you'll find postfix is widely documented and has rich set of easily discoverable resources out there on the web - a search engine is your best resource!</p> <h2>Testing your outgoing email</h2> <p>By default, a command line application called "mail" is installed as part of the bsd-mailx package we installed alongside postfix. You can use it to send test email from the command line on your host to verify you've got things working correctly! The stuff in &lt;&gt; are the keys to hit at the end of the line...</p> <p><code>$ mail you@email.domain&lt;ENTER&gt;</code></p> <p><code>Subject: Testing from your.relay.server.domain&lt;ENTER&gt;<br /> Testing postfix remote host&lt;ENTER&gt;<br /> &lt;CTRL-D&gt;<br /> Cc:&lt;ENTER&gt;</code></p> <p>Typing &lt;CTRL-D&gt; (hold down the Control or Ctrl key on your keyboard and press the "d" key) will finish your message, showing you a "CC:" field, in which you can type in other email addresses if you want to test sending to multiple addresses. When you then hit &lt;ENTER&gt;, it will attempt to send this email. It might take a few minutes to work its way through to the receiving email system (having to run the gauntlet of spam and virus filters on the way).</p> <p>You can also always check the postfix system logs to see what postfix thinks about it using the command above. Hit &lt;SHIFT-F&gt; to have the log update in real time.</p> <h2>Done</h2> <p>Now you've got working outgoing email from your server. That means many higher-level web applications you might install on your infrastructure will work out-of-the-box, because what you've set up, for example, enables the default PHP email service and that used by other stacks.</p> <h2>Sending from Docker Containers</h2> <p>You can configure your server so you can reference it from services you run from Docker containers on your host. You do this by referencing the host, like via an ad hoc SMTP server on your container like <a href="https://marlam.de/msmtp/">msmtp</a>, and you can just reference it as 172.17.0.1, which is the default base IP for Docker hosts from the perspective of Docker containers. You might find it's different on your particular install. In that case, you have to make your Postfix SmartHost accept email for sending from the Docker containers on that server. There're quite a few examples of that among <a href="https://git.oeru.org/explore/projects?utf8=%E2%9C%93&amp;name=docker&amp;sort=latest_activity_desc">my Docker recipes on the OERu's git repository</a>.</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=28&amp;2=field_blog_comments&amp;3=comment" token="lLRkGAi5P6j9iM99_jKG1YxvJLITyB02GoT7oM-A7oA"></drupal-render-placeholder> </div> </section> Mon, 02 Aug 2021 02:08:28 +0000 dave 28 at http://tech.oeru.org Protecting your users with Let's Encrypt SSL Certs http://tech.oeru.org/protecting-your-users-lets-encrypt-ssl-certs <span class="field field--name-title field--type-string field--label-hidden">Protecting your users with Let&#039;s Encrypt SSL Certs</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--lets-encrypt"> <span class="field__item-wrapper"><a href="/taxonomy/term/17" hreflang="en">let&#039;s encrypt</a></span> </div> <div class="field__item field__item--install"> <span class="field__item-wrapper"><a href="/taxonomy/term/11" hreflang="en">install</a></span> </div> <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--_404"> <span class="field__item-wrapper"><a href="/taxonomy/term/13" hreflang="en">14.04</a></span> </div> <div class="field__item field__item--_604"> <span class="field__item-wrapper"><a href="/taxonomy/term/27" hreflang="en">16.04</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--_004"> <span class="field__item-wrapper"><a href="/taxonomy/term/75" hreflang="en">20.04</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" lang="" about="/user/1" typeof="schema:Person" property="schema:name" datatype="" class="username">dave</a></span> <span class="field field--name-created field--type-created field--label-hidden">Thu 08/07/2021 - 14:23</span> <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><a class="visually-hidden focusable skip-link" href="https://tech.oeru.org/node/add/blog_post#main-content">Sk</a>For any website that requires anyone (users or even just a few admins) to transfer secrets to and from it, you want to ensure the data is end-to-end encrypted. Today various browsers (like Firefox) give warnings when you're sending secret data (like passwords) "in the clear", namely unencrypted. In early 2017, Google <a href="http://searchengineland.com/google-starts-giving-ranking-boost-secure-httpsssl-sites-199446">added further urgency</a> to doing the right thing for your users. </p> <p>In the past, getting an SSL certificate to achieve encryption for your domain (the little "lock" icon in browser address bar indicating that your communication with the site is encrypted), was a complicated, expensive proposition, requiring a lot of annoying and time consuming "identity verification" (sometimes via post in the dark old days) and a fee of, in some cases, a couple hundred dollars per year paid to your "SSL Cert Provider" to pay for those administrative services along with the software needed to gin up a long prime number to act as your encryption key (the long string of characters making up your SSL certificate).</p> <p>Thankfully, thanks to the efforts of the <a href="https://letsencrypt.org" title="Let's Encrypt - democratising SSL and making it ubquitous.">Let's Encrypt</a> community, the process is both far far easier, and free of cost. Now there really isn't an excuse for not having an SSL certificate on your site.</p> <p>Members of the Let's Encrypt community have provided a range of useful open source tools you can use to create and maintain certificates on your hosting infrastructure (e.g. the Virtual Machine (VM) on which you're installing web services detailed in the howtos on this site!). In this case we're going to use a tool, "<a href="https://certbot.eff.org/">certbot</a>" provided by the good folks at the <a href="https://eff.org">Electronic Frontier Foundation</a>.</p> <p>For VMs running Ubuntu 18.04 or more recent Long Term Support (LTS) versions of the Ubuntu Linux platform, you should be able to just run:</p> <p><code>sudo apt-get install letsencrypt</code></p> <p>For VMs running Ubuntu 14.04 or 16.04 which are what we use, the install is easy - at your VM command line, run:</p> <pre> <code>sudo add-apt-repository ppa:certbot/certbot sudo apt-get update sudo apt-get install certbot </code></pre> <p>We run Nginx on our VMs, which makes one or more hosted services (normally running in Docker containers) available on the Internet. Strictly speaking, we don't use full "end-to-end" encryption - in our case, on the server-end the encryption terminates at the Nginx server. We, perhaps cavalierly, assume that transfer between the host machine and a Docker container running on that host will be implicitly secure... The only way it could be compromised is if the VM itself is compromised, in which case, the Docker containers running on it could be, too. Avoiding having secure transfer between Nginx on the VM host and the various Docker containers also substantially simplifies setting up each application.</p> <p>Thanks to a service which Nginx provides SNI (or <a href="https://en.wikipedia.org/wiki/Server_Name_Indication">Server Name Indication</a>) - Apache and a few other web servers also provide this - which removes the historical limitation that meant you could only have one SSL certificate per IP address on a web server. The only downside of SNI is that some older browsers (and platforms) don't support it. Since those older technologies are rapidly dying out and it's quite expensive and difficult to have a single IP address for each SSL service on a server, we accept this compromise.</p> <h2>The Let's Encrypt Cert Process</h2> <p>Here's (roughly) how the process works:</p> <ol><li>Point your domain (via A or CNAME record) to point to the/an external IP address on your VM.</li> <li>Set up a domain (or domains) for non-secure hosting (on port 80) via your Nginx instance.</li> <li>The domain's configuration must include a special directory reserved for Let's Encrypt verification content.</li> <li>You request that certbot (on the VM) acquires a certificate for that domain (or domains) at which point <ol><li>the certbot writes a file with a hard-to-guess name to that special directory and requests that the Let's Encrypt infrastructure checks the domain name from outside</li> <li>Let's Encrypt checks that domain name and special directory to see that the expected number appears there, thus verifying that the requesting party actually has the ability to set content at this hard-to-guess filename, and therefore has legitimate claim to being the party controlling the domain name and server.</li> <li>Let's Encrypt registers the certificate request in the name of the party running the certbot (so it can, for example, send emails to the administrator warning them that the certificate needs to be renewed - which happens every 8 weeks or so), and</li> <li>Let's Encrypt sends verification back to your VM's certbot telling it to complete the certificate generation, which it then (digitally) signs in the name of the Let's Encrypt Certificate Authority (which, in turn, is recognised by almost all web browsers out-of-the-box - no mean feat, I can tell you).</li> </ol></li> <li>You get an alert telling you that you have created a valid SSL certificate.</li> <li>You alter your Nginx domain configuration to <ol><li>redirect connections to port 80 (un-encrypted) to port 443 (encrypted), and</li> <li>you set up the 443 configuration including your new certificates.</li> </ol></li> <li>You reload your Nginx configuration, and your site will now be end-to-end encrypted.</li> </ol><h2>The Let's Encrypt Snippet</h2> <p>To make it easy to include the relevant directory info, I recommend that you create a new file in your Nginx configuration (substitute your preferred text editor for "vim" in the following - "nano" is a good choice if you haven't already got a preference):</p> <p><code>sudo mkdir /etc/nginx/includes<br /> sudo vim /etc/nginx/includes/letsencrypt.conf</code></p> <p>and make sure it has the following content (note, I learned this thanks to <a href="https://community.letsencrypt.org/t/how-to-nginx-configuration-to-enable-acme-challenge-support-on-all-http-virtual-hosts/5622">someone else's howto</a> on the global Internet knowledge commons :))</p> <p><code># Rule for legitimate ACME Challenge requests<br /> location ^~ /.well-known/acme-challenge/ {<br />     default_type "text/plain";<br />     # this can be any directory, but this name keeps it clear<br />     root /var/www/letsencrypt;<br /> }</code></p> <p><code># Hide /acme-challenge subdirectory and return 404 on all requests.<br /> # It is somewhat more secure than letting Nginx return 403.<br /> # Ending slash is important!<br /> location = /.well-known/acme-challenge/ {<br />     return 404;<br /> }</code></p> <p>Next, make sure your directory exists (note - you only need to do this once per VM) - it shouldn't need an special permissions - it'll be written by the "root" user, and needs to be readable by the Nginx user, usually "www-data" on a Debian or Ubuntu Linux instance.</p> <p><code>mkdir /var/www/letsencrypt</code></p> <h2>Example Nginx Domain Configuration - unencrypted</h2> <p>Here's an example of a pre-cert Nginx domain configuration for example.org and <a href="http://www.example.org">www.example.org</a> (I usually name the configuration file after the main domain it concerns, so my file would be /etc/nginx/sites-available/example.org) - this should also let you do initial test of your app to make sure it works, before adding the additional complexity of SSL. (<em>Replace example.com (and <a href="http://www.example.com">www.example.com</a>) with your own domain!</em>):</p> <p><code>server {</code></p> <p><code>    listen 80; # this is one of our external IPs on the server.<br />     #listen   [::]:80 default ipv6only=on; ## listen for ipv6<br /><br />     # this root directory isn't really relevant in a proxy situation</code><br /><code>    # so I usually set it to the system default<br />     root /usr/share/nginx/www;<br />     index index.html index.htm;<br /><br />     server_name example.org www.example.org;<br /><br />     access_log /var/log/nginx/example.org_access.log;<br />     error_log /var/log/nginx/example.org_error.log;</code></p> <p><code>    # this is where we include the snippet<br />     include /etc/nginx/includes/letsencrypt.conf;</code></p> <p><code>    # this is just an example of a "proxy" configuration<br />     # for, say, a Docker-based service, exposed on the VM's<br />     # local port 8081<br />     location / {<br />         proxy_read_timeout      300;<br />         proxy_connect_timeout   300;<br />         proxy_redirect          off;<br />         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-Proto   $scheme;<br />         proxy_pass      http://127.0.0.1:8081;<br />     }</code><br /><code>}</code></p> <p>You can make sure that the configuration is visible to Nginx by adding it into the "sites-enabled" directory via a file link</p> <p><code>sudo ln -sf /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled </code></p> <p>Test things to make sure the new configuration doesn't have typos or bad references:</p> <p><code>sudo nginx -t</code></p> <p>and if not, make it live:</p> <p><code>sudo service nginx reload</code></p> <p>You should now be able to go to <a href="http://example.com">http://example.com</a> (or your domain) and you'll hopefully get your proxied application (if it's set up) or an Nginx error (see you nginx error file for more info!).</p> <p>Now it's time to request the certificate!</p> <h2>Example Certbot invocation</h2> <p>Once cerbot is installed, and a domain is configured, it's pretty straightforward to get a certificate.</p> <p>On the first invocation of certbot, you might get a coloured interface that requests your user details (e.g. name and email address) so that Let's Encrypt can register them for the purposes of future emails. They email if one of your certificates is on the verge of expiring, or if there's been a change to Let's Encrypt policy or process. It's worth being on the list. </p> <p>You can request your certificate with the following:</p> <p><code>sudo certbot certonly --webroot -w /var/www/letsencrypt -d example.org -d www.example.org</code></p> <p>If it works, it gratifyingly results in a message that starts with "Congratulations"!</p> <h2>Example Nginx Domain Configuration - unencrypted</h2> <p>Once you've got your certificate, you can reference it in your configuration. We normally set up a redirect from the unencrypted version of the site to the encrypted on (except for the Let's Encrypt verification directory!):</p> <p><code>server {<br />     listen 80; # listen on port 80 on all IPv4 addresses</code><br /><code>    listen [::]:80; # listen on port 80 on all IPv6 addresses</code><br /><code> <br />     root /var/www/html;<br />     index index.html index.htm;<br /><br />     server_name example.org www.example.org;<br /><br />     access_log /var/log/nginx/example.org_access.log;<br />     error_log /var/log/nginx/example.org_error.log;</code></p> <p><code>    include /etc/nginx/includes/letsencrypt.conf;</code></p> <p><code>    # a 302 is a "soft" redirect. A 301 can never be reversed.<br />     location / {<br />         return 302 https://chat.oeru.org$request_uri;<br />     }       <br /> }<br /><br /> server {</code><br /><span style="font-family:monospace"><span style="color:#000000;background-color:#ffffff;">    listen 443 ssl; # listen on port 443 on all IPv4 addresses</span></span><br /><span style="font-family:monospace"><span style="color:#000000;background-color:#ffffff;">    listen [::]:443 ssl; # listen on port 443 on all IPv6 addresses</span></span><br /><br /><code>    # this is a deprecated rule, not required in Ubuntu 20.04's nginx<br />     # ssl on; <br />     ssl_certificate /etc/letsencrypt/live/example.org/fullchain.pem;<br />     ssl_certificate_key /etc/letsencrypt/live/example.org/privkey.pem;</code><br /><code>    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;<br />     ssl_dhparam /etc/ssl/certs/dhparam.pem;<br />     keepalive_timeout 20s;</code></p> <p><code>    access_log /var/log/nginx/example.org_access.log;<br />     error_log /var/log/nginx/example.org_error.log;</code></p> <p><code>    root /var/www/html;<br />     index index.html index.htm;</code><br /><br /><code>    server_name example.org www.example.org;<br />    <br />     # this is just an example of a "proxy" configuration<br />     # for, say, a Docker-based service, exposed on the VM's<br />     # local port 8081<br />     location / {<br />         proxy_read_timeout      300;<br />         proxy_connect_timeout   300;<br />         proxy_redirect          off;<br />         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-Proto   $scheme;<br />         proxy_pass      http://127.0.0.1:8081;<br />     }</code><br /><code>}</code></p> <p>Note - you also need to set up the <code>ssl_dhparam</code> file for this configuration to work. You can do this based on <a href="https://michael.lustfield.net/nginx/getting-a-perfect-ssl-labs-score" title="Setting hp ssl_dhparam">these instructions</a> after installing OpenSSL tools:</p> <p><code>sudo apt-get install openssl</code></p> <p>by running (warning - this can take quite a long time, 5-15 minutes in my experience - the system needs to generate sufficient <a href="https://en.wikipedia.org/wiki/Entropy">entropy</a> to achieve acceptable randomness):</p> <pre class="literal-block"> <code>openssl dhparam -out /etc/ssl/certs/dhparam.pem 4096</code> </pre> <p>When you've set up the file, you can enable it:</p> <p><code>sudo ln -sf /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled</code></p> <p>Test the file to ensure there aren't any syntax errors before reloading nginx:</p> <p><code>sudo nginx -t</code></p> <p>If this shows an error, you'll need to fix the file. If all's well, reload nginx to enable the new configuration:</p> <p><code>sudo service nginx reload</code></p> <p>You should now be able to point your browser at your domain name, and it should automatically redirect you to <a href="https://example.org">https://example.org</a> - and (based on the above configuration, <a href="https://www.example.org">https://www.example.org</a> should work too. You might want to redirect <a href="http://www.example.org">www.example.org</a> to example.org or visa versa).</p> <p>A word to the wise - if it doesn't work, check your firewall settings!</p> <p><strong>Update:</strong> discovered this <a href="https://www.digitalocean.com/community/tutorials/how-to-secure-nginx-with-let-s-encrypt-on-ubuntu-14-04">very well done how-to</a> on Let's Encrypt that offers additional background to this one.</p> <h2>Ongoing Certificate Maintenance</h2> <p>One of the nice things about EFF's certbot is that when it's installed, it also installs a nightly cron task (see <code>/etc/cron.d/certbot</code>) which checks all domains registered on the server for renewals. Assuming your domains have been configured in Nginx as described above, renewals should occur automatically, and you'll just receive a periodic email to let you know that they've happened.</p> <p>If you want to check your renewal status, you can run this:</p> <pre> <code>sudo certbot renew --dry-run</code></pre> <p>Good on you for securing your users and your site!</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=11&amp;2=field_blog_comments&amp;3=comment" token="u_cC5Zw8SKo5_CwG7txdoRLRmx6G2xIvWYWTc95IdY0"></drupal-render-placeholder> </div> </section> Thu, 08 Jul 2021 02:23:06 +0000 dave 11 at http://tech.oeru.org 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" lang="" about="/user/1" typeof="schema:Person" property="schema:name" datatype="" 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-_dEHMneaDCU" 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" typeof="foaf:Image" 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-_dEHMneaDCU" 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" typeof="foaf:Image" 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-_dEHMneaDCU" 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" typeof="foaf:Image" 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-_dEHMneaDCU" 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" typeof="foaf:Image" 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-_dEHMneaDCU" 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" typeof="foaf:Image" 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-_dEHMneaDCU" 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" typeof="foaf:Image" 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-_dEHMneaDCU" 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" typeof="foaf:Image" 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-_dEHMneaDCU" 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" typeof="foaf:Image" 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-_dEHMneaDCU" 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" typeof="foaf:Image" 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-_dEHMneaDCU" 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" typeof="foaf:Image" 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>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 copy 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!):</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