Seafile – Dateisyncronisation

Permalink

Als neuesten Service auf meinem Homeserver habe ich mir Dateisynchronisation auserkoren. Dadurch möchte ich Dateien zwischen den verschiedenen Computern in meinem Haushalt auf dem gleichen Stand halten ohne dabei die Möglichkeit zu verlieren auch offline mit ihnen zu arbeiten.

Eine Software die so etwas ermöglicht ist Seafile. Im Gegensatz zu bekannten Services wie Dropbox oder Google Drive kann man Seafile auf einem eigenen Server betreiben und es gibt eine Community Edition die Open Source ist. Wenn man sich mit Seafile beschäftigt sollte man etwas darauf achten, das es zwei verschiedene Forks gibt. Einerseits das „orginal“ aus China (seafile.com) und einen deutsche Variante unter seafile.de. Wer dazu näheres Wissen will, kann bei Wikipedia mit der Recherche anfangen. Ich beziehe mich im folgenden, ohne bestimmte Gründe, auf die Version der Seafile Ltd. aus China.

Beim Betrieb von Seafile werden verschiedene Informationen in Datenbanken abgelegt. Die Software unterstützt zwei Datenbanksysteme: Zum einen kann man das dateibasierte SQLight verwenden oder man nutzt einen MySQL-Server. Ich verwende erst mal SQLight. Wer gerne MySQL benutzen möchte findet entsprechende Informationen in der Dokumentation von Seafile.

Für die folgende Anleitung ist es wichtig zu wissen das Seafile aus drei Komponenten besteht. Der Seafile Deamon (kurz: Seafile) ist für das Hochladen, Runterladen und Synchronisieren zuständig. Der Seahub ist das Webfrontend in dem unter anderem die Benutzer und die Bibliotheken mit den Dateien verwaltet werden. Die dritte Komponente Ccnet wird vom Seafile-Server intern verwendet. Ein Schaubild dazu gibt es in der Dokumentation.

Vorbereitungen

Bevor ich mich mit der eigentlichen Installation von Seafile beschäftige müssen ein paar Vorbereitungen getroffen werden. Als erstes erzeuge ich einen Benutzer unter dem Seafile später laufen soll:

useradd -r -m -d /opt/seafile -s /bin/false seafile

Dieses Kommando erzeugt einen System-Benutzer (-r) seafile ohne Passwort. Der Benutzer kann sich nicht anmelden weil seine Shell (-s) nicht wirklich eine ist. Als Home-Verzeichnis (-m -d) habe ich das Verzeichnis /opt/seafile/ gewählt da ich dort die Installation vornehmen möchte. Das Verzeichnis /opt/ ist für Software gedacht die am Paketmanager vorbei installiert wird.

Außer einem Benutzer lege ich auch noch ein neues Verzeichnis an in dem später die, durch Seafile verwalteten, Dateien abgelegt werden und berechtige den neuen Benutzer auf diesem Verzeichnis:

mkdir /var/seafile
chown seafile:seafile /var/seafile

Für den Betrieb richte ich auch noch eine eigene IP-Adresse ein damit ich die einzelnen Services auf meinem Server ordentlich voneinander separieren kann. Dazu lege ich eine neue Datei eth0-1 im Ordner /etc/network/interfaces.d/ an. In dieser definiere ich ein neues Interface mittel der folgenden Zeilen:

auto eth0:1
iface eth0:1 inet static
   address 192.0.2.11
   netmask 255.255.255.0
iface eth0 inet6 static
   address 2001:DB8::11
   netmask 32

Die Adressen sind natürlich an das lokale Netzwerk anzupassen. Anschließend initialisiere ich das neue Interface durch den Befehl if-up eth0:1.

Um später die richtige Datei von Seafile herunterladen zu können benötige Ich noch eine Information über mein System. Es gibt nämlich unterschiedliche Downloads für 32-Bit und 64-Bit Systeme. Wenn man diese Information nicht weiß kann man sie mit folgendem Befehl ermitteln:

uname -m

Um die Vorbereitungen abzuschließen installiere ich noch die benötigten Pakete über die Paketverwaltung von Debian:

apt-get install nginx python2.7 libpython2.7 python-setuptools python-imaging python-ldap python-urllib3 sqlite3

Installation

Die im folgenden beschriebene Installation von Seafile ist angelehnt an die offizielle Dokumentation, berücksichtigt aber meine spezifischen Anpassungen. Insbesondere führe ich die Installation mit dem oben eingerichteten unprivilegierten Benutzer durch.

Benutzer wechseln

Damit später alles gut funktioniert wechsle ich vor der eigentlichen Installation zu dem neuen Benutzer seafile:

su - seafile -s /bin/bash

Dadurch befinde ich mich praktischer weise auch gleich in dessen Home-Verzeichnis /opt/seafile/ wo die Installation vorgenommen werden soll.

Download

Auf der Webseite von Seafile kann man im Download-Bereich die benötigte Fassung des Seafile-Servers (32- oder 64-Bit) für Linux ermitteln. Die entsprechende URL hinter dem jeweiligen Link benutze ich im folgenden um das Archiv herunterzuladen und anschließend zu entpacken:

mkdir -p /opt/seafile/installed
cd /opt/seafile/installed
wget --content-disposition https://bintray.com/artifact/download/seafile-org/seafile/seafile-server_6.0.7_x86-64.tar.gz
tar -xzvf *tar.gz -C ../
cd ..

Installationsskript

Für die Installation wechsele ich in das Verzeichnis /opt/seafile/seafile-server_6.0.7/ das durch das Entpacken des Downloads im vorangegangenen Schritt entstanden ist und führen das darin enthaltene Script setup-seafile.sh aus.

cd /opt/seafile/seafile-server-*
./setup-seafile.sh 

Das Script fragt vier Parameter ab die es für die Konfiguration benötigt. Zu erst muss ich einen beliebigen Namen für meine Installation festlegen. Danach wird die IP-Adresse des Servers abgefragt. Hier muss ich diejenige eintragen die ich in den Vorbereitungen festgelegt habe. Als nächstes wird der Port für den Seafile-Server erfragt. Den belasse ich auf dem vorgegebenen Port 8082. Als letztes muss ich noch angeben in welchem Verzeichnis die zu verwaltenden Dateien abzulegen sind. Hierfür habe ich ja extra den Ordner /var/seafile/ vorbereitet.

Um die Installation abzuschließen starte ich Seafile und Seahub erstmalig. Dabei wird auch der Administratoraccount angelegt. Das starten erledigt man mittels spezieller Scripte aus dem Verzeichnis /opt/seafile/seafile-server-latest welches bei der Installation angelegt wurde.

/opt/seafile/seafile-server-latest/seafile.sh start
/opt/seafile/seafile-server-latest/seahub.sh start 8000

Beim Start von Seahub muss ich dazu eine E-Mail-Adresse und ein Passwort eingeben mit denen ich mich später als Administrator anmelden kann. Jetzt kann ich schon mal einen ersten Blick auf Seahub werfen indem ich http://192.0.2.11:8000 in meinem Browser aufrufe.

Außerdem habe ich bemerkt das beim Start eine Warnmeldung ausgegeben wird:

LC_ALL is not set in ENV, set to en_US.UTF-8
./seahub.sh: Zeile 207: Warnung: setlocale: LC_ALL: Kann die Locale nicht ändern (en_US.UTF-8): Datei oder Verzeichnis nicht gefunden

Diese hat etwas mit den Spracheinstellungen zu tun und wird von mir erst mal ignoriert. Beim erstelle des Init-Scripts weiter unten komme ich aber noch einmal darauf zurück.

Anschließend muss ich sowohl Seafile als auch Seahub wieder beendet werden um die nächsten Schritte vornehmen zu können:

/opt/seafile/seafile-server-latest/seahub.sh stop 
/opt/seafile/seafile-server-latest/seafile.sh stop

Nginx als Reverse Proxy

Obwohl Seafile einen eigenen Webserver mitbringt möchte ich doch Nginx verwenden. Das hat den einfachen Grund das ich so eine Transportverschlüsselung einrichten kann. Nach dem ich die im Folgenden beschriebenen Schritte durchgeführt habe, wird Nginx die HTTP-Requests für den Seafile-Server entgegennehmen und die Verschlüsselung managen. Dann reicht er die Anfrage an Seafile und Seahub weiter und gibt die Antwort von diesen, wiederum verschlüsselt, an den Aufrufer zurück. Die Art wie ich Nginx in diesem Fall einsetze nennt man einen Reverse Proxy.

Meine Vorgehensweise ist wiederum angelehnt an die offizielle Dokumentation von Seafile. Die beiden Artikel Config Seahub with Nginx und Enabling Https with Nginx fasse ich im folgenden, angereichert um meine eigenen Vorstellungen, zusammen.

Seafile umstellen

Die Datei /opt/seafile/conf/ccnet.conf muss für den Betrieb mit Nginx geändert werden so das die Service-URL darauf zeigt. Dazu ändere ich den momentanen Wert von SERVICE_URL so ab, dass TLS (HTTPS) genutzt wird und statt dem Port 8082 von Seafile der Standard-TLS-Port 443:

SERVICE_URL = https://192.0.2.11

Ebenfalls ändere ich die Datei /opt/seafile/conf/seahub_settings.py um auch hier den Verweis auf Nginx zu ergänzen. Dazu füge ich die folgende Zeile an die Datei an:

FILE_SERVER_ROOT = https://192.0.2.11/seafhttp

Als drittes ändere ich auch noch die Datei /opt/seafile/conf/seafile.conf. Hier füge ich ebenfalls eine Zeile ein:

host=127.0.0.1

Dadurch erreiche ich das der Seafile Deamon nur noch lokal auf dem Server, und nicht zusätzlich zu Nginx von außen erreichbar ist.

Damit ist die Konfiguration von Seafile abgeschlossen und ich wechsele zu Nginx. Dazu kehre ich mit dem Kommando exit auch vom Benutzer Seafile zu root zurück.

Zertifikate erstellen

Als erste Maßnahme erzeuge ich ein neues Zertifikat für die neue IP-Adresse um damit TLS einrichten zu können:

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

Damit erzeuge ich ein selbstsigniertes Zertifikat das für meine Zwecke ausreichen ist.

Nginx konfigurieren

Der Weg um Seafile mit Nginx zu verknüpfen führt über eine zusätzliche Konfigurationsdatei. Dazu lege ich in /etc/nginx/sites-available/ eine neue Datei namens seafile an. Darin wird die Verknüpfung zum Seahub mittels der Schnittstellentechnik FastCGI hergestellt. Auch der Proxy für den Seafile-Server wird hier eingerichtet. Ich lehne mich dabei an die Vorgaben aus der Dokumentation von Seafile an.

Der erste Server-Block in dieser Datei befasst sich mit „normalen“ HTTP für die gewählte IP auf Port 80. Das einzige was ich hier einstelle ist eine Weiterleitung auf HTTPS welches ich wiederum im nächsten Block konfiguriere.

server {
        listen 192.0.2.11:80;
        listen [2001:DB8::11]:80;
        return 301 https://$server_name$request_uri;
}

Der zweite Server-Block hat vier Abschnitte. Im ersten definiere ich die allgemeinen Parameter wie IP, Port, TLS-Zertifikate und ein paar einfache Sicherheitseinstellungen.

server {
   listen 192.0.2.11:443 ssl;
   listen [2001:DB8::11]:443 ssl;

   ssl_certificate /etc/nginx/ssl/sync.files.home.crt;
   ssl_certificate_key /etc/nginx/ssl/sync.files.home.key;
   ssl_protocols   TLSv1.2;
   ssl_ciphers     HIGH:!aNULL:!MD5;

   add_header Strict-Transport-Security "max-age=31536000; includeSubDomains";
   server_tokens off;
   proxy_set_header X-Forwarded-For $remote_addr;

   …
}

Anschließend konfiguriere ich die Fast-CGI-Schnittstelle zum Seahub und mache diesen somit unter dem Wurzelverzeichnis (/) der Nginx-Webseite verfügbar.

server {
   …
   location / {
      fastcgi_pass    127.0.0.1:8000;
      fastcgi_param   SCRIPT_FILENAME     $document_root$fastcgi_script_name;
      fastcgi_param   PATH_INFO           $fastcgi_script_name;

      fastcgi_param   SERVER_PROTOCOL     $server_protocol;
      fastcgi_param   QUERY_STRING        $query_string;
      fastcgi_param   REQUEST_METHOD      $request_method;
      fastcgi_param   CONTENT_TYPE        $content_type;
      fastcgi_param   CONTENT_LENGTH      $content_length;
      fastcgi_param   SERVER_ADDR         $server_addr;
      fastcgi_param   SERVER_PORT         $server_port;
      fastcgi_param   SERVER_NAME         $server_name;
      fastcgi_param   REMOTE_ADDR         $remote_addr;

      fastcgi_param   HTTPS on;
      fastcgi_param   HTTP_SCHEME https;

      fastcgi_read_timeout 36000;

      access_log   /var/log/nginx/seahub.access.log;
      error_log    /var/log/nginx/seahub.error.log;
   }
   …
}

Die Synchronisationsmechanismen für die Dateien (der Seafile Deamon) binde ich über eine Proxy-Anweisung an den Pfad /seafhttp/. Dieser ist damit ebenfalls über HTTPS erreichbar.

server {
   …
   location /seafhttp {
      rewrite ^/seafhttp(.*)$ $1 break;
      proxy_pass http://127.0.0.1:8082;
      client_max_body_size 0;
      proxy_connect_timeout  36000s;
      proxy_read_timeout  36000s;
      proxy_send_timeout  36000s;
      send_timeout  36000s;
   }
   …
}

Abschließend definiere ich auch noch den Pfad /media/. Dieser Pfad stellt einige statische Dateien für Seahub bereit und verweist einfach auf einen Ordner innerhalb des Installationsverzeichnisses.

server {
   …
   location /media {
      root /opt/seafile/seafile-server-latest/seahub;
   }
}

Nach einem Neustart von Nginx mittels /etc/init.d/nginxs restart ist dessen Konfiguration abgeschlossen. Jetzt noch einen Test bevor ich weiter mache. Dazu wieder mit dem Benutzer Seafile sowohl den Deamon als auch den Seahub starten. Wobei Seahub im Fast-CGI-Modus laufen muss:

su - seafile -s /bin/bash
/opt/seafile/seafile-server-latest/seafile.sh start
/opt/seafile/seafile-server-latest/seahub.sh start-fastcgi
exit

Jetzt sollte über https://192.0.2.11/ das Webinterface aufrufbar sein. Dabei muss die Warnung des Browsers vor dem unbekannten TLS-Zertifikats weggeklickt werden.

Init-Script

Um Seafile besser in Debian zu integrieren bedarf es eines Init-Scripts. Dieses sorgt dann dafür das Seafile beim Booten des Servers gestartet wird und auch beim herunterfahren oder beim Neustart sauber beendet wird. Eine passende Vorlage kann, mal wieder, dem Artikel Start Seafile at System Bootup aus der Dokumentation von Seafile entnommen werden. Damit das Script allerdings funktioniert muss der Befehl sudo ersetzt werden da dieser unter Debian nicht unbedingt zur Verfügung steht. An den relevanten Stellen bin ich daher auf su ausgewichen.

Eine zweite Änderung am Init-Script führt mich zu der Warnmeldung bezüglich der Locale zurück die beim Starten von Seafile auftritt. Die Ursache für diese Fehlermeldung liegt darin das ich bei der Installation von Debian die deutsche Sprache ausgewählt habe. Seafile versucht nun auf eine englisch Umgebung umzustellen was der Benutzer seafile aber gar nicht darf. Daher setzte ich eine Umgebungsvariable LC_ALL auf die gewünschte deutsche Locale de_DE.UTF-8 und der Server startet ohne Fehler.

#!/bin/sh

### BEGIN INIT INFO
# Provides:          seafile-server
# Required-Start:    $local_fs $remote_fs $network
# Required-Stop:     $local_fs
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: Starts Seafile Server
# Description:       starts Seafile Server
### END INIT INFO

# Change the value of "user" to linux user name who runs seafile
user=seafile

# Change the value of "seafile_dir" to your path of seafile installation
# usually the home directory of $user
seafile_dir=/opt/seafile
script_path=${seafile_dir}/seafile-server-latest
seafile_init_log=${seafile_dir}/logs/seafile.init.log
seahub_init_log=${seafile_dir}/logs/seahub.init.log

# Change the value of fastcgi to true if fastcgi is to be used
fastcgi=true
# Set the port of fastcgi, default is 8000. Change it if you need different.
fastcgi_port=8000

#
# Write a polite log message with date and time
#
echo -e "\n \n About to perform $1 for seafile at `date -Iseconds` \n " >> ${seafile_init_log}
echo -e "\n \n About to perform $1 for seahub at `date -Iseconds` \n " >> ${seahub_init_log}

case "$1" in
   start)
      su -c "${script_path}/seafile.sh ${1} >> ${seafile_init_log}" -s /bin/bash ${user}
      if [ $fastcgi = true ];
      then
            su -c "export LC_ALL='de_DE.UTF-8' && ${script_path}/seahub.sh ${1}-fastcgi ${fastcgi_port} >> ${seahub_init_log}" -s /bin/bash ${user}
      else
            su -c "${script_path}/seahub.sh ${1} >> ${seahub_init_log}" -s /bin/bash ${user}
      fi
   ;;
   restart)
      su -c "${script_path}/seafile.sh ${1} >> ${seafile_init_log}" -s /bin/bash ${user}
      if [ $fastcgi = true ];
      then
            su -c "${script_path}/seahub.sh ${1}-fastcgi ${fastcgi_port} >> ${seahub_init_log}" -s /bin/bash ${user}
      else
            su -c "${script_path}/seahub.sh ${1} >> ${seahub_init_log}" -s /bin/bash ${user}
      fi
   ;;
   stop)
      su -c "${script_path}/seahub.sh ${1} >> ${seahub_init_log}" -s /bin/bash ${user}
      su -c "${script_path}/seafile.sh ${1} >> ${seafile_init_log}" -s /bin/bash ${user}
   ;;
   *)
      echo "Usage: /etc/init.d/seafile-server {start|stop|restart}"
      exit 1
   ;;
esac

Dieses Script speichere ich unter /etc/init.d/seafile-server und mache es ausführbar:

sudo chmod +x /etc/init.d/seafile-server

Anschließend registiere ich das Script noch damit es beim Hochfahren auch ausgeführt wird.

sudo update-rc.d seafile-server defaults

Wenn nach einem Neustart des Servers, diesmal ist die Hardware gemeint, Seahub im Browser aufrufbar ist hat alles geklappt und die Installation ist vollständig.

Nächste Schritte

Einige Aspekte lasse ich hier bewusst außen vor – der Artikel ist auch so schon lang genug:

Wer nicht gern mit IP-Adressen hantiert kann natürlich auch Hostnamen festlegen und diesen an stelle der IP benutzen.

Wen die Fehlermeldungen zum TLS-Zertifikat stören kann man auch eine eigene CA(Certificate Authority) aufsetzen um hier Besserung zu schaffen.

Etwas mehr Sicherheit? Firewallregeln für Seafile sind recht einfach umzusetzen.

Für den laufenden Betrieb sollte man nötige Updates im Auge behalten und einspielen.

Auch Backups sind ein wichtiges Thema um nicht eines Tages in einem Scherbenhaufen zu stehen.