Wer Dateien mit anderen teilen oder gemeinsam bearbeiten möchte, setzt gerne auf Dropbox, Google Docs oder Skydrive. Diese Dienste sind etabliert, funktionieren zuverlässig und sind einfach zu bedienen. Doch spätestens seit den Enthüllungen von Edward Snowden ist das Thema Datensicherheit aktueller denn je und viele fragen sich, ob es wirklich nötig ist, die eigenen Daten auf Servern im Ausland zu speichern, wo sie schutzlos fremden Nachrichtendiensten ausgeliefert sind. Gerade für kleinere Büros oder Selbständige bieten sich Open-Source-Lösungen an, um die Daten in eigener Regie zu verwalten. In diesem Artikel wird die Software Owncloud als Alternative zu Dropbox beschrieben.

Owncloud deshalb, weil es sehr einfach zu installieren ist und praktisch auf jedem Webspace läuft, der über PHP und eine Datenbank verfügt. Im Gegensatz zu den bisher hier vorgestellten RaspberryPi-Projekten stößt man mit Owncloud an die Grenzen der Leistungsfähigkeit des kleinen Tausendsassas. Damit die eigene Wolke trotzdem reibungslos läuft, bedarf es einiger Optimierungen. Das Ergebnis ist dann ein sehr sparsamer eigener Cloud-Dienst, der neben der Dateisynchronisierung von Dropbox noch viele weitere Dienste bietet, so auch einen Webkalender wie man ihn z.B. von Google kennt.

Los geht’s

Als erstes muss natürlich der Raspberry zusammengebaut und mit einem passenden Betriebssystem versehen werden. Wie das geht, ist in dem NAS-Artikel von Martina Rüdiger ausführlich beschrieben. Dort findet sich auch eine Liste der benötigten Hard- und Software (lediglich die Kühlkörper fehlen, die sollte man dem Raspi aber bei diesem Projekt mit spendieren). Am besten arbeitet man den Artikel Schritt für Schritt bis zum Einbinden der USB-Festplatte durch. Ist das erledigt, geht es an die Installation von Owncloud.

Aus Perfomancegründen installieren wir nicht das übliche Duo aus Apache2 Webserver und MySQL-Datenbank. Statt dessen nehmen wir den schlankeren Webserver Nginx und die weniger Ressourcen beanspruchende Datenbank sqlite3.

Installation Schritt für Schritt

Schritt 1: RaspberryPi übertakten

Auf der Kommandozeile öffnen wir das RaspberryPi Software Configuration Tool.

sudo raspi-config

Dort wählen wir den Punkt Overclock an, bestätigen den Warnhinweis und wählen, wie stark wir den Raspberry Pi übertakten möchten. Ich empfehle den Modus High. Bei Turbo kann es wohl zu Instabilitäten kommen, wenn das Netzteil nicht mindestens 1500 mA liefert. Die Auswahl dann mit Enter bestätigen.

Zurück im Hauptmenü beenden wir das Tool und booten den Raspberry neu, da die Übertaktung erst nach dem Neustart wirksam wird.

Schritt 2: SWAP erweitern

Die SWAP ist eine Datei in der Linux Daten aus dem Arbeitsspeicher auslagert, so wie bei Windows in der Auslagerungsdatei. Die SWAP sollte doppelt so groß sein wie der RAM. Bei einem RaspberryPi B ist der RAM 512 MB groß, d.h. SWAP wird auf 1024 MB eingestellt.

Dazu wechseln wir zum Root-User

sudo su

und erzeugen das SWAP-File mit

echo "CONF_SWAPSIZE=1024" > /etc/dphys-swapfile dphys-swapfile setup

Als nächstes wird das SWAP-File aktiviert:

dphys-swapfile swapon

Und wir melden uns wieder vom Root-User ab.

Exit

Schritt 3: nginx mit PHP und Datenbank installieren

Die Installation erfolgt wieder mit dem Paketmanager APT:

sudo apt-get install nginx

Damit Nginx den RaspberryPi nicht überlastet, passen wir noch einige Prozesse an:

sudo sed -i "s/worker_processes 4;/worker_processes 1;/g" /etc/nginx/nginx.conf
sudo sed -i "s/worker_connections 768;/worker_connections 128;/g" /etc/nginx/nginx.conf

Jetzt kann man Nginx starten:

sudo /etc/init.d/nginx start

Als nächstes installieren wir PHP (in Form von php5-fpm) mit einigen Standarderweiterungen:

sudo apt-get install php5 php5-fpm php-pear php5-common php5-mcrypt php5-mysql php5-cli php5-gd

Jetzt muss PHP in nginx aktiviert werden. Dazu bearbeiten wir die Nginx Konfigurationsdatei

sudo nano /etc/nginx/sites-available/default

und ersetzen hier den Abschnitt


# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
# #location ~ \.php$ {
# fastcgi_split_path_info ^(.+\.php)(/.+)$;
# # NOTE: You should have "cgi.fix_pathinfo = 0;" in php.ini
# # # With php5-cgi alone:
# fastcgi_pass 127.0.0.1:9000;
# # With php5-fpm:
# fastcgi_pass unix:/var/run/php5-fpm.sock;
# fastcgi_index index.php;
# include fastcgi_params;
#}

# deny access to .htaccess files, if Apache's document root
# concurs with nginx's one
#
#location ~ /\.ht {
# deny all;
#}

durch


# pass the PHP scripts to PHP-FPM server listening on unix socket
location ~ \.php$ {
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass unix:/var/run/php5-fpm.sock;
fastcgi_index index.php;
include fastcgi_params;
}

# deny access to .htaccess files
location ~ /\.ht {
deny all;
}

Damit index.php direkt geladen wird, ersetzen wir noch

index index.html index.htm;

durch

index index.html index.htm index.php;

Jetzt speichern wir die Änderung mit Strg-X und bestätigen mit „Y“ (für „yes“). Zum Abschluss installieren wir noch das PHP-Modul php-apc (für ein einfaches Caching) und sqlite3 als Datenbank.

sudo apt-get install php-apc php5-sqlite sqlite3

Jetzt können wir Nginx und PHP neu starten.

sudo /etc/init.d/nginx restart
sudo /etc/init.d/php5-fpm restart

Schritt 4: PHP konfigurieren

Besonders wichtig ist für Owncloud, dass man auch sehr große Dateien hochladen und synchronisieren kann. Dazu muss die php.ini angepasst werden. Bei meiner Installation habe ich das Limit auf 1024 MB eingestellt, damit können bis zu 1 GByte große Dateien verarbeitet werden. Hinweis: bei handelsüblichen Webspace-Paketen existiert hier oft ein Flaschenhals, wenn der Provider einen (i.d.R. sehr niedrigen) Wert fest eingestellt hat, der nicht geändert werden kann. Bevor man ein Paket bucht, sollt man diesen Wert erfragen.

Zum Bearbeiten der php.ini geben wir folgendes ein:

sudo nano /etc/php5/fpm/php.ini

und suchen die folgenden Zeilen (Hinweis: sie stehen nicht direkt untereinander):

upload_max_filesize = 2M

post_max_size = 8M

Dort ändern wir die Werte auf

upload_max_filesize = 1024M

post_max_size = 1024M

Bei dieser Gelegenheit definieren wir auch noch den temporären Upload-Pfad und aktivieren das Caching. Dazu tragen wir am Ende der php.ini folgende Zeilen ein :

upload_tmp_dir = /srv/http/owncloud/data
extension = apc.so
apc.enabled = 1
apc.include_once_override = 0
apc.shm_size = 256

Abschließend speichern wir die php.ini, legen den Ordner an, den wir gerade als temporären Uploadpfad definiert haben und setzen die notwendigen Rechte

sudo mkdir -p /srv/http/owncloud/data
sudo chown www-data:www-data /srv/http/owncloud/data

Schritt 5: Nginx anpassen

Damit Owncloud später direkt unter der IP-Adresse bzw. einer DynDNS-URL ohne Pfadangabe erreichbar ist, ersetzen wir in

sudo nano /etc/nginx/sites-available/default
root /usr/share/nginx/www;

durch

root /var/www/owncloud;

Owncloud ist standardmäßig für den Betrieb unter Apache2 ausgelegt und bringt daher eine htaccess-Datei mit, mit der Nginx nicht umgehen kann. Daher ändern wir in

sudo nano /etc/nginx/sites-available/default

location / # First attempt to serve request as file, then # as directory, then fall back to displaying a 404 try_files $uri $uri/ /index.html;
# Uncomment to enable naxsi on this location
# include /etc/nginx/naxsi.rules
}
 
in
 

client_max_body_size 10G; # set max upload size
fastcgi_buffers 64 4K;
rewrite ^/caldav(.*)$ /remote.php/caldav$1 redirect;
rewrite ^/carddav(.*)$ /remote.php/carddav$1 redirect;
rewrite ^/webdav(.*)$ /remote.php/webdav$1 redirect;
error_page 403 = /core/templates/403.php;
error_page 404 = /core/templates/404.php;

 

location = /robots.txt {
        allow all;
        log_not_found off;
        access_log off;
    }

location ~ ^/(data|config|\.ht|db_structure\.xml|README) {
            deny all;
    }

location / {
            # The following 2 rules are only needed with webfinger
            rewrite ^/.well-known/host-meta /public.php?service=host-meta last;
            rewrite ^/.well-known/host-meta.json /public.php?service=host-meta-json last;
            rewrite ^/.well-known/carddav /remote.php/carddav/ redirect;
            rewrite ^/.well-known/caldav /remote.php/caldav/ redirect;
            rewrite ^(/core/doc/[^\/]+/)$ $1/index.html;
            try_files $uri $uri/ index.php;
    }

location ~ ^(.+?\.php)(/.*)?$ {
            try_files $1 = 404;
            include fastcgi_params;
            fastcgi_param SCRIPT_FILENAME $document_root$1;
            fastcgi_param PATH_INFO $2;
            fastcgi_param HTTPS on;
            fastcgi_pass unix:/var/run/php5-fpm.sock;
    }

# Optional: set long EXPIRES header on static assets
    location ~* ^.+\.(jpg|jpeg|gif|bmp|ico|png|css|js|swf)$ {
            expires 30d;
            # Optional: Don't log access to assets
            access_log off;
    }

Jetzt starten wir Nginx und php5-fpm neu

sudo /etc/init.d/nginx restart
sudo /etc/init.d/php5-fpm restart

Schritt 6: Owncloud herunterladen und installieren

Nun ist es an der Zeit Owncloud herunterzuladen. Die aktuelle Version findet man unter https://owncloud.org/install/ (zum Zeitpunkt der Erstellung dieses Artikel war die aktuelle Version die 7.0.4). Achtung: nicht den Web-Installer runterladen, sondern das volle „Archive File for Server Owners“! Anschließend entpacken wir Owncloud, löschen das heruntergeladene Archiv-File und weisen den Dateien die notwendigen Rechte zu. Am einfachsten geht das wieder über die Kommandozeile:

sudo mkdir /var/www cd /var/www 
sudo wget http://download.owncloud.org/community/owncloud-7.0.4.tar.bz2 
sudo tar xvf owncloud-7.0.4.tar.bz2 
sudo rm owncloud-7.0.4.tar.bz2 
sudo chown -R www-data:www-data /var/www

Jetzt rufen wir OwnCloud im Browser auf und erhalten über http://<IP/DynDNS-Domain> ( durch die IP-Adresse oder DynDNS-Domain des RaspberryPis ersetzen), die Installationsoberfläche von Owncloud. Dort tragen wir den gewünschten Benutzernamen und Passwort für den ersten Benutzer ein. Datenbankeinstellungen müssen wir keine vornehmen, da wir eine SQLite Datenbank verwenden.

Den Pfad zur externen USB-Festplatte, die wir zu Beginn angeschlossen haben, tragen wir unter Fortgeschritten > Datenverzeichnis ein.

Die Fertigstellung der Installation dauert ca. zwei Minuten. In dieser Zeit ist der Browser am Laden und gibt keine weitere Rückmeldung. Also nicht ungeduldig werden Wink .

Schritt 7: Cron-Job einrichten

Damit Owncloud regelmäßige Arbeiten im Hintergrund erledigt, richten wir noch einen Cronjob ein. Das sorgt auf dafür, dass Owncloud dauerhaft performanter läuft.

sudo crontab -u www-data -e

Am Ende der Datei die folgende Zeile einfügen:

*/10 * * * * php -f /var/www/owncloud/cron.php

Nun sorgen wir noch dafür, dass die durch den Cronjob erledigten Arbeiten nicht zusätzlich noch im Browser ausgeführt werden. Dazu in der Owncloud-Oberfläche in „Dein Benutzername > Administration > Cron die Einstellung von AJAX auf Cron ändern.

Schritt 8: SSL einrichten

Zwar läuft der Owncloud-Server jetzt schon, aber der Zugriff erfolgt bisher nur ungesichert. Das ändern wir jetzt.

Als erstes erstellen wir selber ein SSL-Zertifikat für Nginx. Bei den Fragen in der Eingabeaufforderung geben wir lediglich bei „Country Name“ den Wert DE für Deutschland und bei Common Name die DynDNS-Domain des Raspis ein. Bei den restlichen Fragen können wir mit „Enter“ den Standardwert verwenden.

Achtung: Sowohl der Owncloud Client als auch der Browser wird später warnen, dass das SSL-Zertifikat nicht vertrauenswürdig ist. Der Grund ist, dass wir dieses selbst signiert haben. Diese Warnung kann also ignoriert werden. Auf der Kommandozeile geben wir jetzt ein

sudo mkdir /etc/nginx/ssl
sudo openssl genrsa -out /etc/nginx/ssl/owncloud.key 4096
sudo openssl req -new -sha256 -key /etc/nginx/ssl/owncloud.key -out /etc/nginx/ssl/owncloud.csr
sudo openssl x509 -req -sha256 -days 3650 -in /etc/nginx/ssl/owncloud.csr -signkey /etc/nginx/ssl/owncloud.key -out /etc/nginx/ssl/owncloud.crt

Als nächstes müssen in der folgenden Datei noch einige Änderungen vornehmen.

sudo nano /etc/nginx/sites-available/default

Hier ersetzen wir diesen Block


server {
#listen   80; ## listen for ipv4; this line is default and implied
#listen   [::]:80 default_server ipv6only=on; ## listen for ipv6

 

root /var/www/owncloud;
index index.html index.htm index.php;

# Make site accessible from http://localhost/
server_name localhost;

client_max_body_size 10G; # set max upload size
fastcgi_buffers 64 4K;

rewrite ^/caldav(.*)$ /remote.php/caldav$1 redirect;
rewrite ^/carddav(.*)$ /remote.php/carddav$1 redirect;
rewrite ^/webdav(.*)$ /remote.php/webdav$1 redirect;

error_page 403 = /core/templates/403.php;
error_page 404 = /core/templates/404.php;

location = /robots.txt {
allow all;
log_not_found off;
access_log off;
}

location ~ ^/(data|config|\.ht|db_structure\.xml|README) {
deny all;
}

location / {
# The following 2 rules are only needed with webfinger
rewrite ^/.well-known/host-meta /public.php?service=host-meta last;
rewrite ^/.well-known/host-meta.json /public.php?service=host-meta-json last;
rewrite ^/.well-known/carddav /remote.php/carddav/ redirect;
rewrite ^/.well-known/caldav /remote.php/caldav/ redirect;
rewrite ^(/core/doc/[^\/]+/)$ $1/index.html;

try_files $uri $uri/ index.php;
}

location ~ ^(.+?\.php)(/.*)?$ {
try_files $1 = 404;

include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$1;
fastcgi_param PATH_INFO $2;
fastcgi_param HTTPS on;
fastcgi_pass unix:/var/run/php5-fpm.sock;
}

# Optional: set long EXPIRES header on static assets
location ~* ^.+\.(jpg|jpeg|gif|bmp|ico|png|css|js|swf)$ {
expires 30d;

# Optional: Don't log access to assets
access_log off;
}

location /doc/ {
alias /usr/share/doc/;
autoindex on;
allow 127.0.0.1;
allow ::1;
deny all;
}

# Only for nginx-naxsi used with nginx-naxsi-ui : process denied request
#location /RequestDenied {
# proxy_pass http://127.0.0.1:8080;   
#}

#error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
#
#error_page 500 502 503 504 /50x.html;
#location = /50x.html {
# root /usr/share/nginx/www;
#}

# pass the PHP scripts to PHP-FPM server listening on unix socket
location ~ \.php$ {
    try_files $uri =404;
    fastcgi_split_path_info ^(.+\.php)(/.+)$;
    fastcgi_pass unix:/var/run/php5-fpm.sock;
    fastcgi_index index.php;
    include fastcgi_params;
}

# deny access to .htaccess files
location ~ /\.ht {
    deny all;
}

# deny access to .htaccess files, if Apache's document root
# concurs with nginx's one
#
#location ~ /\.ht {
# deny all;
#}
}

durch

server {
    listen 80;
    server_name 192.168.1.xxx;
    rewrite ^ https://$server_name$request_uri? permanent; # enforce https
}

 

server {
    listen 443 ssl;
    server_name 192.168.1.xxx;
    ssl_certificate /etc/nginx/ssl/owncloud.crt;
    ssl_certificate_key /etc/nginx/ssl/owncloud.key;

root /var/www/owncloud;
index index.php;

client_max_body_size 10G; # set max upload size
fastcgi_buffers 64 4K;

rewrite ^/caldav(.*)$ /remote.php/caldav$1 redirect;
rewrite ^/carddav(.*)$ /remote.php/carddav$1 redirect;
rewrite ^/webdav(.*)$ /remote.php/webdav$1 redirect;

error_page 403 = /core/templates/403.php;
error_page 404 = /core/templates/404.php;

location = /robots.txt {
allow all;
log_not_found off;
access_log off;
}

location ~ ^/(data|config|\.ht|db_structure\.xml|README) {
deny all;
}

location / {
rewrite ^/.well-known/host-meta /public.php?service=host-meta last;
rewrite ^/.well-known/host-meta.json /public.php?service=host-meta-json last;

rewrite ^/.well-known/carddav /remote.php/carddav/ redirect;
rewrite ^/.well-known/caldav /remote.php/caldav/ redirect;

rewrite ^(/core/doc/[^\/]+/)$ $1/index.html;

try_files $uri $uri/ index.php;
}

location ~ ^(.+?\.php)(/.*)?$ {
try_files $1 = 404;

include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$1;
fastcgi_param PATH_INFO $2;
fastcgi_param HTTPS on;
fastcgi_pass unix:/var/run/php5-fpm.sock;
}

location ~* ^.+\.(jpg|jpeg|gif|bmp|ico|png|css|js|swf)$ {
expires 30d;
# Optional: Don't log access to assets
access_log off;
}

location ~ \.php$ {
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass unix:/var/run/php5-fpm.sock;
fastcgi_index index.php;
include fastcgi_params;
}

location ~ /\.ht {
deny all;
}
}

Dabei ersetzen wir die beiden Zeilen mit der IP-Adresse „192.168.1.xxx“ durch die richtige IP-Adresse des Raspberrys bzw. durch die DynDNS-Domain. Die Datei speichern und noch einmal Nginx und php-fpm neustarten.

sudo /etc/init.d/nginx restart
sudo /etc/init.d/php5-fpm restart

Hinweis: damit der Owncloud-Server auch aus dem Internet erreichbar ist, müssen im Router die Ports 80 und, falls SSL verwendet wird, 443 freigegeben werden.

Geschafft!

Der eigene Owncloud-Server ist auf dem Raspberry Pi installiert und sollte eine ausreichende Performance bieten. Wem die Leistung nicht genügt, der sollte den leistungsfähigeren BananaPi in Erwägung ziehen.

Wer auch Kalender/Kontakte über Owncloud synchronisieren möchte, kann die folgenden URL-Strukturen verwenden. Die in „<>“ stehenden Werte müssen (einschließlich der „<>“ ) wie gehabt durch die IP-/DynDNS-Adresse ersetzt werden.

Ohne SSL
CalDAV (allgemein): http://<IP/DynDNS>/remote.php/caldav/
CalDAV (für iOS/OS X): http://<IP/DynDNS>/remote.php/caldav/principals/[username]/

CardDAV (alle Geräte): http://<IP/DynDNS>/remote.php/carddav/addressbooks/[username]/[cal name]

Mit SSL
CalDAV (allgemein): https://<IP/DynDNS>/remote.php/caldav/
CalDAV (für iOS/OS X): https://<IP/DynDNS>/remote.php/caldav/principals/[username]/

CardDAV (alle Geräte): https://<IP/DynDNS>/remote.php/carddav/addressbooks/[username]/[cal name]

Fazit

Im laufenden Betrieb ist mir aufgefallen, dass der Server anfängt zu schwächeln, wenn sehr viele Dateien synchronisiert werden sollen. Zum Testen habe ich zum einen wenige sehr große Videodateien mit insgesamt ca. 40 GB Volumen hochgeladen. Hierbei ist der Flaschenhals eindeutig der Upload der DSL-Verbindung. Der Raspberry selber lief klaglos und nach gut einem Tag war alles hochgeladen. Im zweiten Test habe ich ebenfalls rund 40 GB hochgeladen, dieses mal aber viele kleine Dateien, insgesamt über 50.000! Das hat der Raspi zwar auch gestemmt, aber bis alles synchronisiert war, dauerte es rund 10 Tage. Der Engpass war hier wohl die CPU, die durch die vielen Datenbankzugriffe an ihre Grenzen kam.

Alles in allem ein schönes Projekt, das nicht nur die eigenen Daten wieder heim holt, sondern auch noch Geld spart. Die Gesamtkosten für die Hardware beliefen sich inkl. Festplatte auf ca. 100 €. Damit steht jetzt knapp ein Terabyte Cloud-Speicher zur Verfügung. Bei Dropbox kostet diese Speichermenge 9,99 € pro Monat. Und da ich den Cloud-Speicher auch für meine berufliche Arbeit verwende, müssten wir sogar die Dropbox für Unternehmen buchen, womit die Kosten schon auf 12 € pro Nutzer und Monat steigen würden. Dann zwar mit unbegrenztem Speicherplatz, aber das eine Terabyte ist derzeit schon weit mehr als gebraucht wird.

Wer noch mehr über Owncloud und Owncloud-Clients lesen möchte, sollte sich noch diesen Artikel von Dirk Wagner zu Gemüte führen.

Nachtrag: Optimierung bei häufigen Fehlermeldungen

Wenn man eine große Zahl Dateien synchronisiert, kommt es unter Umständen zu zahlreichen Fehlermeldungen, die man im Owncloud-Client sehen kann. In der Regel sind das Meldungen wie 

"504 Gateway Time-out" oder "502 Bad Gateway" 

In der Log-Datei von PHP-fpm findet man dann Einträge mit 

"server reached max_children setting (5), consider raising it" 

Um das Problem zu lösen muss man die zugehörige Konfigurationsdatei bearbeiten: 

sudo nano /etc/php5/fpm/pool.d/www.conf

Dort sucht man die folgenden Einträge (Hinweis: sie stehen in der conf-Datei nicht unbedingt direkt untereinander!): 

pm = dynamic
pm.max_children = 5

und ändert diese in 

pm = static
pm.max_children = 20

Anschließend PHP neu starten mit 

sudo /etc/init.d/php5-fpm restart

Das Synchronisierungsverhalten sollte jetzt deutlich besser sein und die Zahl der Fehler auch bei großen Dateimengen wesentlich geringer werden. 

Links

Erfahrungsbericht zu Owncloud: http://auge.de/usermagazin/internet/meine-eigene-cloud

Offizielle Webseite von Nginx http://nginx.org/

Offizielle Webseite von ownCloud: https://owncloud.org/

Offizielle Webseite von Sqlite: http://sqlite.org/

RaspberryPi installieren: http://auge.de/usermagazin/hardware/raspberry-pi-preisguenstige-nas


 

Kommentare