Build your Nextcloud Server using one shell script

updated: May, 14th, 2018: Updated to TLSv1.3

The initial script ( will install your self hosted Nextcloud within few minutes fully automated. Your server will be built of:

  • Fail2Ban (Nextcloud and SSH jails)
  • MariaDB
  • Nextcloud 13.0.2
  • NGINX 1.14
  • OpenSSL 1.1.0h
  • PHP 7.2.5
  • Redis-Server
  • self signed or Let’s Encrypt SSL using the second script
  • UFW (22, 80, 443)

The only precondition for the script is to use Ubuntu 18.04 LTS as your server OS. You will find a script for Ubuntu 16.04.4 LTS either, it is called At least but optionally you may request a ssl certificate from letsencrypt by issuing the second script called “”.

Ready to go? Let’s start:

(1) Build your self hosted Nextcloud server

If you are on Ubuntu 18.04 LTS:

sudo -s
cd /usr/local/src
git clone
cd install-nextcloud
chmod +x

If you are on Ubuntu 16.04.4 LTS:

sudo -s
cd /usr/local/src
git clone
cd install-nextcloud
chmod +x

… be patient

Open your browser and call the shown URL from your shell

Nextcloud is already up, optimized and running!

(2) Optionally: Request your ssl certificate from Let’s Encrypt

Before you request your certificate ensure that your web-ports (80+443) are forwared to your server and your dyndns is properly configured to point to your server!

sudo -s
cd /usr/local/src/install-nextcloud
chmod +x

You only have to enter your DYNDNSNAME (YOUR.DEDYN.IO).

Then LetsEncrypt will ask you for

  • your email adress
Enter email address (used for urgent renewal and security notices) (Enter 'c' to cancel):
  • to agree to their Terms of Service

and finally

  • if you are willing to share your email address with the Electronic Frontier Foundation
Y or N

Wait while your certificates are obtained.

If you receive this message:


Call: and enjoy your Nextcloud


your server is up and running using a certificate from Let’s Encrypt.

Enjoy your self hosted Nextcloud.

Carsten Rieger

45 Responses

  1. Perry Clements says:

    Fantastic work!

    I installed the first script into on fresh 1804 ubuntu server (no graphics) running in a VM under KVM/Qemu, 1604LTS host.

    Everything worked until I added a trusted domain for a local computer, then port 80 and 443 closed.

    This is the command I used to add the trusted domain:

    perry@nc1:~$ sudo -u www-data php /var/www/nextcloud/occ config:system:set trusted_domains 1 –value=G75VW.local
    System config value trusted_domains => 1 set to string G75VW.local

    perry@nc1:~$ sudo -u www-data php /var/www/nextcloud/occ config:system:get trusted_domains

    The trusted domain seem to add ok but port 80 and 443 closed.

    Any ideas why or hints to troubleshoot?

    • To be honest, no. Sure your ports were closed?! ufw status verbose or netstat -ant | egrep '(:80|:443) .*:.*ESTABLISHED' | awk '{print $5}' | cut -d: -f1 | sort | uniq -c

      • Perry Clements says:

        The ports looks open when I run ufw from inside using SSH but they looked closed from the outside using nmap and the website stops responding after the trusted domain is added.

        Before adding the trusted domain…

        perry@nc1:~$ sudo ufw status verbose
        Status: active
        Logging: on (medium)
        Default: deny (incoming), allow (outgoing), disabled (routed)
        New profiles: skip

        To Action From
        — —— —-
        80/tcp ALLOW IN Anywhere
        443/tcp ALLOW IN Anywhere
        22/tcp ALLOW IN Anywhere
        80/tcp (v6) ALLOW IN Anywhere (v6)
        443/tcp (v6) ALLOW IN Anywhere (v6)
        22/tcp (v6) ALLOW IN Anywhere (v6

        perry@G75VW:~$ nmap
        Starting Nmap 7.70 ( ) at 2018-05-23 12:42 ADT
        Nmap scan report for
        Host is up (0.00077s latency).
        Not shown: 997 filtered ports
        22/tcp open ssh
        80/tcp open http
        443/tcp open https

        Added the trusted domain here…

        perry@G75VW:~$ nmap
        Starting Nmap 7.70 ( ) at 2018-05-23 12:48 ADT
        Nmap scan report for
        Host is up (0.00085s latency).
        Not shown: 997 filtered ports
        22/tcp open ssh
        80/tcp closed http
        443/tcp closed https

        perry@nc1:~$ sudo ufw status verbose
        Status: active
        Logging: on (medium)
        Default: deny (incoming), allow (outgoing), disabled (routed)
        New profiles: skip

        To Action From
        — —— —-
        80/tcp ALLOW IN Anywhere
        443/tcp ALLOW IN Anywhere
        22/tcp ALLOW IN Anywhere
        80/tcp (v6) ALLOW IN Anywhere (v6)
        443/tcp (v6) ALLOW IN Anywhere (v6)
        22/tcp (v6) ALLOW IN Anywhere (v6

        • Perry Clements says:

          Looks like fail2ban was the problem. I unbaned the IP and things are now working.

          2018-05-23 15:36:41,013 fail2ban.jail [1179]: INFO Jail ‘sshd’ started
          2018-05-23 15:36:41,014 fail2ban.jail [1179]: INFO Jail ‘nextcloud’ started
          2018-05-23 15:41:50,470 fail2ban.filter [1179]: INFO [nextcloud] Found – 2018-05-23 15:41:50
          2018-05-23 15:41:50,868 fail2ban.filter [1179]: INFO [nextcloud] Found – 2018-05-23 15:41:50
          2018-05-23 15:46:15,225 fail2ban.filter [1179]: INFO [nextcloud] Found – 2018-05-23 15:46:14
          2018-05-23 15:46:15,791 fail2ban.actions [1179]: NOTICE [nextcloud] Ban

  2. Mateusz says:

    Hey Carsten. First of all great work, though I cannot seem to get it to work (PINE64+ board with Ubuntu Xenial Minimal installed) as the browser returns an error (Unsecure connection).
    Referring to the problem above I came up with a suggestion. Are you keen on developing a remove shell script for the whole install? I think it would help many.

    • No i won’t. But what is your problem in detail? Did you issue the second script or only the first? what errors were written in the log-files (e.g. nginx or letsencrypt or nextcloud.log) Please send me an emal with further informaion i will try to help you. OK? Cheers, Carsten

  3. Zane says:

    Hi, erstmal vielen dank für deine Arbeit!
    Ich würde sehr gerne dein Skript nutzen und würde gerne vorher wissen ob ich noch irgendwas anpassen muss/sollte.
    Ich habe einen ODROID X4U ( Ubuntu Minimal 16.04, armhf, 2GB RAM, 8 Kerne, 8GB eMMC. + 2* 1TB Ext. USB HDDs..)
    Außerdem sollen die “Daten” auf einer der beiden Externen HDDs unter /media/usb1tb/data liegen. (Die andere ist für Backup)
    Sollte ich das im Skript anpassen oder kann ich das erstmal so durchlaufen lassen und hinterher ändern in der PHP.conf ?

    • Zane says:


      • Zane says:

        Ich habe mir das Script nochmal angeguckt, wenn ich das richtig sehe muss ich um das Data Verzeichnis auf die externe HDD zu verschieben hier:

        ###create folders
        mkdir -p /var/nc_data
        ###apply permissions
        chown -R www-data:www-data /var/nc_data

        das Verzeichnis von /var/nc_data auf /media/usb1tb/data ändern

        und hier auch:
        “###create a fail2ban Nextcloud jail
        logpath = /var/nc_data/nextcloud.log”

        Und dann halt noch in der config.php
        Ist das dann so richtig?

  4. Andreas says:

    Hallo Carsten,
    ein super script. es läuft sweit alles, nur wenn ich mir ein SSL Zertifikat erstellen lasse mit dem 2 script habe ich keine Verbindung von ausen mehr.

    • Andreas says:

      unter Ubuntu server 18.04 LTS

    • Hallo Andreas, vielen Dank. Was meinst Du mit keine Verbindung von außen? Laufen alle Services? Welcher Fehler tritt auf?

      • Andreas says:

        das Zertifikat wird erstellt. Wenn ich micht über meine DynDns anmelden möchte bekomme ich nur eine weiße Seite, intern bekomme ich mein Nextcloud angezeigt.
        Es laufen alle instanzen soweit ich das beurteilen kann. Gruß Andreas

  5. ylaung says:

    Hi, you have mentioned the precondition for this script as Ubuntu 18.04 LTS OS.
    Will this still work for Ubuntu 16.04 LTS OS?

  6. Keven says:

    Hi Carsten
    wäre es denn möglich so ein scipt auch für arch linux arm zu erstellen denn ich setzte auf meinem C2 arch linux ein und finde es etwas aufwendig von den Ubuntu anleitungen auf Arch linux umzudenken, dennoch finde ich all deine anleitungen echt super.
    Gruß Keven

    • Hi Keven, prinzipiell ja und gern, ABER: ich habe kein Arch Linux im Einsatz und es bindet so schon sehr viel Zeit. Also mittelfristig eher nein, langfristig ja. Servus, Carsten

  7. robbie says:

    Hi Carsten,
    Thanks for the script. I’ve tried this twice on digitalocean but all I get is HTTP ERROR 500 when trying to access in the browser. Went through the process, added ssl, and even edited trusted_domains in config.php to reflect the ip, and made sure overwrite.cli.url was pointing to the right domain in config.php. Still no luck.

    • robbie says:

      I found the problem. For some reason, the script changes both the database name and username to in config.php even though I entered just nextcloud. So it was a database error. Fixed it and everything works fine now.

      • Strange. The database will be set to nextcloud hard coded.
        CREATE DATABASE nextcloud CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
        You were only asked for the name of the db-user and its password.
        Maybe someting went wrong while editing the config.php?

        • robbie says:

          I did enter ‘nextcloud’ for db-user. however, the first time i opened config.php, it had appended to db-user and db-name. I thought that was the way it should be until i checked the logs and found database connection errors.

  8. Michael says:

    Thank you very much for these manual, I have utilized your step-by-step guide before and now these scripts. Great work!
    I came across a small issue on a new installation of Ubuntu Server 18.04 with the

    With “sh ./” i would always get the error ‘syntax error: “(” unexpected’. Only when omitting ‘sh’ and just enter ‘./’ the script would run without issue.

    Just thought to mention this as a small thank you for your great work!


  9. Bernd says:

    funktioniert das Script auch mit UBUNTU Server 18.04?

    Gruß Bernd

    • Noch nicht verifiziert – daher würde ich es in dieser Version noch nicht für 18.04 LTS einsetzen. Eine neue Version für Ubuntu 18.04 folgt in wenigen Tagen…

  10. Andreas Bonadt says:

    Das ssl-script hat mit meiner Konfiguration nicht funktioniert. Problem war die Zeile:
    sudo -u www-data sed -in ‘s/’$YOURSERVERNAME’/’$DYNDNSNAME’/’ /var/www/nextcloud/config/config.php

    Mein Servername ist nextcloud und mein Datenbanknutzer ist nextclouduser. Der wurde dann zu nextcloud.domain.deuser. In der gleichen Weise wurden die Servernamen (die vorher schon FQDN waren) verändert zu

    Ansonsten waren Deine Scripts super hilfreich! Danke für die Arbeit!
    Viele Grüße,

  11. Jackson Storm says:

    Hi Carsten.

    Vielen Dank für das coole Script. Dieses nimmt mir jede Menge händischer Arbeit ab.

    Ich habe eine Frage dazu:
    Wie wird in diesem Fall genau die Sicherheit des MySQL-Benutzers “nextcloud” (dessen Passwort ja ebenfalls nextcloud lautet) gewährleistet? Ist es nicht sinnvoller, hier ein eigenes Passwort zu vergeben bzw. den Benutzer individiuell zu erstellen und abzusichern?


  12. Japhy says:

    I am new to shell scripts and have never used Nginx. But I would love to try this! One thing: how does Nginx handles vhosts. How does this work if I want to install in a certain vhost?

  13. kelbot says:

    Does this script have a way to setup letsencrypt or would I have to do it manually?

    • currently you have to do it manually:
      sudo -s && letsencrypt certonly -a webroot --webroot-path=/var/www/letsencrypt --rsa-key-size 4096 -d YOUR.DEDYN.IO
      Then modify the file /etc/nginx/ssl.conf regarding your dyn-dns
      sudo -s && sudo vi /etc/nginx/ssl.conf
      I prepared this file already for such a scenario 😉 – you will find commented rows regarding let’s encrypt…

    • From now (just refresh your sources from git) you may request your certificate issuing a script either.

  14. If you use functions you can do more with less. Here is an example:

    update_and_clean() {
    apt update
    apt upgrade -y
    apt autoclean -y
    apt autoremove -y

    Eeach time you want to run those commands you only need to run: update_and_clean – in other words, you can make your code cleaner.

    Welcome to join us on Github: 🙂

Leave a Reply

Your email address will not be published. Required fields are marked *