Motivation

    Um eigene Dateien mobil verfübgar zu haben, nutze ich schon länger auf einem vHost eine eigene Nextcloud Instanz. Durch diesen Schritt entgehe ich somit einer möglichen Dateianalyse, wie Google und Amazon sie in ihrer Cloud durchführen. Hoch sensible Daten lege ich aber auch dort nicht ab.

    Fortlaufende  Speicherauswertungen meines vHosts zeigen, dass der verfügbare Speicher in den letzten Monaten stark abgenommen hat. Die Erweiterung des Speichers geht bei vHost fast immer mit der  Erweiterung von RAM und CPU einher, was ich a) beides nicht benötige und b) mir schlicht zu teuer ist. Aus diesem Grund suche ich schon länger nach Alternativen, wie z.B die Ablage verschlüsselte Daten in der Cloud. Diese implizieren aber, dass die Verschlüsselung der Daten a) ohne Fehler implementiert wurde und b) sinkende Speicherpreise nicht auf einmal den Grundsatz aushebeln, dass ein Knacken der Verschlüsselung entweder zu zeitaufwendig ist, oder die Daten nach erfolgreicher Verschlüsselung zu alt sind um noch Nutzbar zu sein (Stichwort Quantencomputer).

    Die sich somit ergebenden Anforderungen sind:

    1. Kostengünstige erweiterung des Cloud Speichers (< 10 € pro Monat)
    2. Remote Zugriff von jedem Endgerät möglich
    3. Reduzierung des Angriffsvektors (Remote Zugang auf ein Minimum)
    4. Keine Auswirkung auf primäres Speichersystem, wenn der Erweiterungsspeicher nicht verfügar ist
    5. Nicht lokale Speicher muss über ein WAN taugliches Protokoll angebunden werden (kein SMB, CIFS, etc)
    6. Technisch stabile und zuverlässige Anbindung

    Lösung

    Nextcloud lässt bereits seit einigen Versionen die Einbindung von externem Speicher zu. Es liegt somit Nahe, einfach zwei Nextcloud Instanzen zu einer federated Cloud zu verbinden. Die Kosten für lokale NAS Festplatten (2x 8 TB für 318 € mit 3 Jahren Garantie) belaufen sich – ohne Strom oder NAS Anschaffungskosten – auf 8,83 € pro Monat.

    Vergleicht man die Speicher- und Transferkosten wird klar ersichtlich, dass Cloud-Speicher aktuell zu teuer ist. Ich greife der Tabelle vor weg: Anforderung 1 erfüllt.

    Cloud Anbieter Kosten pro Monat Downloadkosten (einmalig z.B. für
    Umzug zu anderem Anbieter)
    Gesamtkosten ($/€)
    Backblaze $0,005 * 8000 =$40 $0,01 * 8000 = $80 $120 / 102 €
    Amazon $0,021 * 8000 = $168 $0,05 * 8000 = $400 $568 / 484 €
    Microsoft Azure $0,018 * 8000 = $144 $0,05 * 8000 = $400 $544 / 464 €
    Google Cloud $0,020 * 8000 =$160 $0,08 * 8000 = $640 $800 / 682 €

    Durch die Integration externen Speichers in die bereits bestehende Cloud Instanz ist ein Remote-Zugang ohne Zusatzwerkzeuge möglich. Anforderung 2 erfüllt.

    Wer nunr denkt, dass ein NAS im Internet nicht die zweite Anforderung erfüllt, hat prinzipiell Recht. Allerdings kann durch die Nutzung der existierenden Cloud-Instanz jeglicher Verkehr zum NAS per Firewall geblockt werden, es sie denn, er stammt vom vHost. Anforderung 2 erfüllt.
    Nach Tests kann ich sagen, dass eine nicht Erreichbarkeit des NAS Systems (z.B. Shutdown etc) in der primären Nextcloud Instanz nur mit einer Meldung quittiert wird, dass der externe Speicher aktuell nicht verfügbar ist. Anforderung 4 erfüllt.
    Das WAN taugliche Protokoll können wir durch die Nutzung von HTTPS als gegeben abhaken (Anforderung 5). Lediglich die Stabilität muss sich im Praxiseinsatz erst noch bewähren.

    Nach all der Theorie nun zur Einrichtung der Lösung.

    Synology DS212+

    Installation notwendiger Pakete

    Leider gibt es bis heute kein fertiges Nextcloud Paket für Synology Systeme. Aus diesem Grund müssen folgende Pakete installiert werden:

    • Web station
    • Apache HTTP Server 2.4
    • PHP 7.0
    • MariaDB 10

    Wie das geht wird jeder Besitzer eine NAS Systems nach 1 Stunde herausgefunden haben.

    Konfiguration der Pakete

    Nach der Installation aller Pakete setzten Sie als erstes das Datenbankkennwort von MariaDB 10 zurück.

    Im Anschluss daran öffnen Sie die Web Station. Ändern Sie in den Allgemeinen Einstellung die Optionen wie nachfolgen dargestellt.

    Gehen Sie nun in die PHP-Einstellungen. Legen Sie dort ein neues PHP Profil an. Nehmen Sie die Einstellungen wie in der nachfolgenden Abbildung vor.

    Die zu aktivierenden Erweiterungen hierbei sind:

    • bz2
    • curl
    • gd
    • mysqli
    • openssl
    • pdo_mysql
    • zip

    Ändern Sie darüber hinaus auf der Registerkarte Kern zur Performanceverbesserung folgende Werte:

    Installation Nextcloud

    Aktivieren Sie nun in den Einstellung unter Terminal & SNMP die SSH Verbindung.

    Nutzen Sie z.B Putty um sich per SSH zu verbinden. Als Benutzername ist admin mit dem DSM Kennwort zu verwenden. Anschließend wechseln Sie mit mit sudo -i in den Root Kontext.

    user@linux:~> ssh admin@nas
    admin@nas's password:
    Permission denied, please try again.
    admin@nas's password:
    admin@nas:/$ sudo -i
    Password:
    root@nas:~#

    Wechseln Sie anschließend nach /volume1/web, laden Sie Nextcloud herunter und extrahieren es.

    root@nas:~# cd /volume1/web/
    root@nas:/tmp# wget https://download.nextcloud.com/server/releases/nextcloud-13.0.5.zip
    --2018-07-30 20:48:39--  https://download.nextcloud.com/server/releases/nextcloud-13.0.5.zip
    Resolving download.nextcloud.com... 88.198.160.133
    Connecting to download.nextcloud.com|88.198.160.133|:443... connected.
    HTTP request sent, awaiting response... 200 OK
    Length: 61358118 (59M) [application/zip]
    Saving to: 'nextcloud-13.0.5.zip'
    
    nextcloud-13.0.5.zip                  100%[=======================================================================>]  58.52M  8.21MB/s    in 7.3s    
    
    2018-07-30 20:48:49 (8.06 MB/s) - 'nextcloud-13.0.5.zip' saved [61358118/61358118]
    
    root@nas:/tmp# 7z nextcloud-13.0.5.zip

    Um die Dateirechte für alle Ordner zu setzen und dabei die spätere Nextcloud Instanz nicht zu härten, kann folgendes Script verwendet werden.

    #!/bin/bash
    ocpath='/volume1/web/nextcloud/'
    htuser='http'
    htgroup='http'
    rootuser='root'
    
    printf "Creating possible missing Directories\n"
    mkdir -p $ocpath/data
    mkdir -p $ocpath/assets
    mkdir -p $ocpath/updater
    
    printf "chmod Files and Directories\n"
    find ${ocpath}/ -type f -print0 | xargs -0 chmod 0640
    find ${ocpath}/ -type d -print0 | xargs -0 chmod 0750
     
    printf "chown Directories\n"
    chown -R ${htuser}:${htgroup}  $ocpath
    chown -R ${rootuser}:${htgroup} ${ocpath}/
    chown -R ${htuser}:${htgroup} ${ocpath}/apps/
    chown -R ${htuser}:${htgroup} ${ocpath}/assets/
    chown -R ${htuser}:${htgroup} ${ocpath}/config/
    chown -R ${htuser}:${htgroup} ${ocpath}/data/
    chown -R ${htuser}:${htgroup} ${ocpath}/themes/
    chown -R ${htuser}:${htgroup} ${ocpath}/updater/
     
    chmod +x ${ocpath}/occ
     
    printf "chmod/chown .htaccess\n"
    if [ -f ${ocpath}/.htaccess ]
     then
      chmod 0644 ${ocpath}/.htaccess
      chown ${rootuser}:${htgroup} ${ocpath}/.htaccess
    fi
    if [ -f ${ocpath}/data/.htaccess ]
     then
      chmod 0644 ${ocpath}/data/.htaccess
      chown ${rootuser}:${htgroup} ${ocpath}/data/.htaccess
    fi

    Anschließend kann über die Adresse des NAS Systems http://<IP-Adresse>/nextcloud die Installation über die Webseite beendet werden.

    <Abbildung Nextcloud Web Setup mit Benutzername root>

    Port Forwarding und Ausstellung Zertifikat

    Nach Abschluss der Installation muss die Nextcloud-Instanz gleich ein für die Öffentlichkeit gültiges Zertifikat erhalten. Dies macht eine spätere Anbindung der vHost-Nextcloud Instanz einfacher.
    Auf Routern mit einer GUI ist der Port 443 auf das NAS umzuleiten. Da ich einen Linux basierten Router verwende läuft dies bei mir (noch) per iptables.

    iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 443 -j DNAT --to 192.168.10.2:443

    Nach Freischaltung des Ports kann im DSM über Einstellungen – Sicherheit ein Zertifikat von Letsencrpyt ausgestellt werden.

    Dieses ist nach erfolgreicher Ausstellung über die Schaltfläche Konfigurieren für alle Web Dienste zu hinterlegen.

    Ist dies erfolgt, sollten die Firewallregeln neu geladen werden, um die vorherige Regeln wieder zu entfernen. Im Anschluss daran wird eine neue Regel gesetzt, die nur Verbindungen des vHosts über Port 443 auf das NAS weiterleitet.

    iptables -t nat -A PREROUTING -i eth0 -s <vHost-IP> -p tcp --dport 443 -j DNAT --to 192.168.10.2:443

    Anbindung externer Nextcloud Speicher

    Nun ist der Zeitpunkt gekommen, das lokale NAS als externen Speicher in Nextcloud zu integrieren. Hierzu muss in der vHost Nextcloud Instanz die Erweiterung für externen Speicher installiert und aktiviert sein.
    Die Einrichtung selber erfolgt dann wie folgt:

    Am Anschluss daran ist der lokale Speicher in der Cloud erreichbar und entsprechend markiert.

    Remount Nextcloud Anwenderverzeichnis

    Damit nun Heimnetzwerknutzer nicht lokale auch Nextcloud verwenden müssen, mounte ich die Nextcloud Ordner in die Homeshares der Anwender.

    mount -o bind /volume1/web/nextcloud/data/Benutzer1/files/ /volume1/Benutzer1/

    Daraus ergeben sich nun allerdings zwei Notwendigkeiten.

    1. Nextcloud hat keine Kentniss über lokal per SMB abgelegte Dateien und zeigt diese somit nicht in der Web GUI oder App an
    2. Der mount muss nach jedem Neustart ausgeführt werden

    Anpassung PHP 7.0 Cli

    Nextcloud bietet ein cli-Tool namens occ. Mit diesem Werkzeug können über den Parameter files:<scan|cleanup|…> zum Beispiel verwaiste Datenbankeinträge bereinigt werden (Datei per SMB gelöscht) oder fehlende Dateien (per SMB erstellt) indiziert werden.

    Führt man occ allerdings als root über die shell aus, erfolgt sofort die Ernüchterung:

    sudo -u http php70 /volume1/web/nextcloud/occ -v files:scan --all
    An unhandled exception has been thrown:
    Doctrine\DBAL\DBALException: Failed to connect to the database: An exception occured in driver: could not find driver in /volume1/web/nextcloud/lib/private/DB/Connection.php:64
    Stack trace:
    #0 /volume1/web/nextcloud/3rdparty/doctrine/dbal/lib/Doctrine/DBAL/Connection.php(429): OC\DB\Connection->connect()
    #1 /volume1/web/nextcloud/3rdparty/doctrine/dbal/lib/Doctrine/DBAL/Connection.php(389): Doctrine\DBAL\Connection->getDatabasePlatformVersion()
    #2 /volume1/web/nextcloud/3rdparty/doctrine/dbal/lib/Doctrine/DBAL/Connection.php(328): Doctrine\DBAL\Connection->detectDatabasePlatform()
    #3 /volume1/web/nextcloud/3rdparty/doctrine/dbal/lib/Doctrine/DBAL/Connection.php(623): Doctrine\DBAL\Connection->getDatabasePlatform()
    #4 /volume1/web/nextcloud/lib/private/DB/Connection.php(151): Doctrine\DBAL\Connection->setTransactionIsolation(2)
    #5 /volume1/web/nextcloud/3rdparty/doctrine/dbal/lib/Doctrine/DBAL/DriverManager.php(172): OC\DB\Connection->__construct(Array, Object(Doctrine\DBAL\Driver\PDOMySql\Driver), Object(Doctrine\DBAL\Configuration), Object(Doctrine\Common\EventManager))
    #6 /volume1/web/nextcloud/lib/private/DB/ConnectionFactory.php(152): Doctrine\DBAL\DriverManager::getConnection(Array, Object(Doctrine\DBAL\Configuration), Object(Doctrine\Common\EventManager))
    #7 /volume1/web/nextcloud/lib/private/Server.php(628): OC\DB\ConnectionFactory->getConnection('mysql', Array)
    #8 /volume1/web/nextcloud/3rdparty/pimple/pimple/src/Pimple/Container.php(113): OC\Server->OC\{closure}(Object(OC\Server))
    #9 /volume1/web/nextcloud/lib/private/AppFramework/Utility/SimpleContainer.php(116): Pimple\Container->offsetGet('OCP\\IDBConnecti...')
    #10 /volume1/web/nextcloud/lib/private/ServerContainer.php(132): OC\AppFramework\Utility\SimpleContainer->query('OCP\\IDBConnecti...')
    #11 /volume1/web/nextcloud/lib/private/AppFramework/Utility/SimpleContainer.php(164): OC\ServerContainer->query('OCP\\IDBConnecti...')
    #12 /volume1/web/nextcloud/3rdparty/pimple/pimple/src/Pimple/Container.php(109): OC\AppFramework\Utility\SimpleContainer->OC\AppFramework\Utility\{closure}(Object(OC\Server))
    #13 /volume1/web/nextcloud/lib/private/AppFramework/Utility/SimpleContainer.php(116): Pimple\Container->offsetGet('DatabaseConnect...')
    #14 /volume1/web/nextcloud/lib/private/ServerContainer.php(132): OC\AppFramework\Utility\SimpleContainer->query('DatabaseConnect...')
    #15 /volume1/web/nextcloud/lib/private/Server.php(1511): OC\ServerContainer->query('DatabaseConnect...')
    #16 /volume1/web/nextcloud/lib/private/Server.php(332): OC\Server->getDatabaseConnection()
    #17 /volume1/web/nextcloud/3rdparty/pimple/pimple/src/Pimple/Container.php(113): OC\Server->OC\{closure}(Object(OC\Server))
    #18 /volume1/web/nextcloud/lib/private/AppFramework/Utility/SimpleContainer.php(116): Pimple\Container->offsetGet('OC\\Authenticati...')
    #19 /volume1/web/nextcloud/lib/private/ServerContainer.php(132): OC\AppFramework\Utility\SimpleContainer->query('OC\\Authenticati...')
    #20 /volume1/web/nextcloud/lib/private/Server.php(336): OC\ServerContainer->query('OC\\Authenticati...')
    #21 /volume1/web/nextcloud/3rdparty/pimple/pimple/src/Pimple/Container.php(113): OC\Server->OC\{closure}(Object(OC\Server))
    #22 /volume1/web/nextcloud/lib/private/AppFramework/Utility/SimpleContainer.php(116): Pimple\Container->offsetGet('OC\\Authenticati...')
    #23 /volume1/web/nextcloud/lib/private/ServerContainer.php(132): OC\AppFramework\Utility\SimpleContainer->query('OC\\Authenticati...')
    #24 /volume1/web/nextcloud/lib/private/AppFramework/Utility/SimpleContainer.php(164): OC\ServerContainer->query('OC\\Authenticati...')
    #25 /volume1/web/nextcloud/3rdparty/pimple/pimple/src/Pimple/Container.php(109): OC\AppFramework\Utility\SimpleContainer->OC\AppFramework\Utility\{closure}(Object(OC\Server))
    #26 /volume1/web/nextcloud/lib/private/AppFramework/Utility/SimpleContainer.php(116): Pimple\Container->offsetGet('OC\\Authenticati...')
    #27 /volume1/web/nextcloud/lib/private/ServerContainer.php(132): OC\AppFramework\Utility\SimpleContainer->query('OC\\Authenticati...')
    #28 /volume1/web/nextcloud/lib/private/Server.php(352): OC\ServerContainer->query('OC\\Authenticati...')
    #29 /volume1/web/nextcloud/3rdparty/pimple/pimple/src/Pimple/Container.php(113): OC\Server->OC\{closure}(Object(OC\Server))
    #30 /volume1/web/nextcloud/lib/private/AppFramework/Utility/SimpleContainer.php(116): Pimple\Container->offsetGet('OCP\\IUserSessio...')
    #31 /volume1/web/nextcloud/lib/private/ServerContainer.php(132): OC\AppFramework\Utility\SimpleContainer->query('OCP\\IUserSessio...')
    #32 /volume1/web/nextcloud/lib/private/AppFramework/Utility/SimpleContainer.php(164): OC\ServerContainer->query('OCP\\IUserSessio...')
    #33 /volume1/web/nextcloud/3rdparty/pimple/pimple/src/Pimple/Container.php(109): OC\AppFramework\Utility\SimpleContainer->OC\AppFramework\Utility\{closure}(Object(OC\Server))
    #34 /volume1/web/nextcloud/lib/private/AppFramework/Utility/SimpleContainer.php(116): Pimple\Container->offsetGet('UserSession')
    #35 /volume1/web/nextcloud/lib/private/ServerContainer.php(132): OC\AppFramework\Utility\SimpleContainer->query('UserSession')
    #36 /volume1/web/nextcloud/lib/private/Server.php(1380): OC\ServerContainer->query('UserSession')
    #37 /volume1/web/nextcloud/lib/private/Server.php(688): OC\Server->getUserSession()
    #38 /volume1/web/nextcloud/3rdparty/pimple/pimple/src/Pimple/Container.php(113): OC\Server->OC\{closure}(Object(OC\Server))
    #39 /volume1/web/nextcloud/lib/private/AppFramework/Utility/SimpleContainer.php(116): Pimple\Container->offsetGet('OC\\App\\AppManag...')
    #40 /volume1/web/nextcloud/lib/private/ServerContainer.php(132): OC\AppFramework\Utility\SimpleContainer->query('OC\\App\\AppManag...')
    #41 /volume1/web/nextcloud/lib/private/AppFramework/Utility/SimpleContainer.php(164): OC\ServerContainer->query('OC\\App\\AppManag...')
    #42 /volume1/web/nextcloud/3rdparty/pimple/pimple/src/Pimple/Container.php(109): OC\AppFramework\Utility\SimpleContainer->OC\AppFramework\Utility\{closure}(Object(OC\Server))
    #43 /volume1/web/nextcloud/lib/private/AppFramework/Utility/SimpleContainer.php(116): Pimple\Container->offsetGet('AppManager')
    #44 /volume1/web/nextcloud/lib/private/ServerContainer.php(132): OC\AppFramework\Utility\SimpleContainer->query('AppManager')
    #45 /volume1/web/nextcloud/lib/private/Server.php(1684): OC\ServerContainer->query('AppManager')
    #46 /volume1/web/nextcloud/lib/private/legacy/app.php(332): OC\Server->getAppManager()
    #47 /volume1/web/nextcloud/lib/private/legacy/app.php(113): OC_App::getEnabledApps()
    #48 /volume1/web/nextcloud/lib/base.php(662): OC_App::loadApps(Array)
    #49 /volume1/web/nextcloud/lib/base.php(1081): OC::init()
    #50 /volume1/web/nextcloud/console.php(46): require_once('/volume1/web/ne...')
    #51 /volume1/web/nextcloud/occ(11): require_once('/volume1/web/ne...')

    Grund sind fehlende Module in der PHP 7.0 ini. Um diese zu aktivieren, müssen entsprechende Links erstellt werden.

    ln -s /volume1/@appstore/PHP7.0/usr/local/lib/php70/modules/pdo_mysql.so /usr/local/lib/php70/modules/pdo_mysql.so
    ln -s /volume1/@appstore/PHP7.0/usr/local/lib/php70/modules/gd.so /usr/local/lib/php70/modules/
    ln -s /volume1/@appstore/PHP7.0/usr/local/lib/php70/modules/bz2.so /usr/local/lib/php70/modules/
    ln -s /volume1/@appstore/PHP7.0/usr/local/lib/php70/modules/mysqli.so /usr/local/lib/php70/modules/
    ln -s /volume1/@appstore/PHP7.0/usr/local/lib/php70/modules/openssl.so /usr/local/lib/php70/modules/
    ln -s /volume1/@appstore/PHP7.0/usr/local/lib/php70/modules/zip.so /usr/local/lib/php70/modules/
    ln -s /volume1/@appstore/PHP7.0/usr/local/lib/php70/modules/posix.so /usr/local/lib/php70/modules/
    ln -s /volume1/@appstore/PHP7.0/usr/local/lib/php70/modules/curl.so /usr/local/lib/php70/modules/

    Anschließend erfolgt die Aktivierung über die php.ini. Hierzu wird die verwende php.ini über die php70 cli ausgelesen

    root@nas:/volume1/web# /usr/local/bin/php70 -i | grep php.ini
    Configuration File (php.ini) Path => /usr/local/etc/php70
    Loaded Configuration File => /usr/local/etc/php70/php.ini

    Anschließend können die Erweiterungen durch das Einfügen der nachfolgenden Zeilen hinter extension_dir aktiviert werden.

    vim /usr/local/etc/php70/php.ini
    
    extension = pdo_mysql.so
    extension = gd.so
    extension = bz2.so
    extension = mysqli.so
    extension = openssl.so
    extension = zip.so
    extension = posix.so
    extension = curl.so

    Anschließend kann der Befehl occ erfolgreich ausgeführt werden.

    root@nas:~# sudo -u http php70 /volume1/web/nextcloud/occ files:scan --all
    
    Scanning files for 3 users
    Starting scan for user 1 out of 3 (user1)
    Starting scan for user 2 out of 3 (user2)
    Starting scan for user 3 out of 3 (user3)
    
    +---------+-------+--------------+
    | Folders | Files | Elapsed time |
    +---------+-------+--------------+
    | 399     | 2578  | 00:02:43     |
    +---------+-------+--------------+

     

    Geplante Aufgaben

    Kleinere Optimierungen

    @eadir in Nextcloud ausblenden

    @eadir ist ein von Synology verwendetes Verzeichnis in dem verschiedene Informationen von Synology abgelegt werden. Dieses in Nextcloud anzuzeigen bietet dem Anwender keinen Mehrwert. Aus diesem Grund habe ich dieses Verzeichnis sowie .lnk Dateien ausgeblendet. Hierzu muss in Nextcloud die Custom CSS App installiert werden. Anschließend kann als Admin in den Einstellungen über Theming definiert werden, welche Dateien oder Ordner ausgeblendet werden sollen.

    tr[data-file*=".url"] {
      display: none !important;
    }
    
    tr[data-file*=".lnk"] {
      display: none !important;
    }
    
    tr[data-file="@eaDir"] {
      display: none !important;
    }

    Quelle: https://help.nextcloud.com/t/hide-file-folders/7145/7

    Leave A Reply