Seafile: Bye, bye, Dropbox?

One of the many good reasons to set up a self-hosted server (besides the obvious fun factor ;-)) is to escape, at lest partially, from all the massive spying and snooping, be it by corporations or governments. (In the second case: good luck.) A key component in any modern web offering is of course cloud-based file synchronization (e.g. Dropbox, Onedrive, etc.).

Fortunately there are some free and open source alternatives to these commercial services. The main contenders are OwnCloud and Seafile. While the former aims at becoming a complete platform of cloud-services (including calendar, contacts, editing office documents, etc.), the latter does one thing and one thing only: handling files stored on a central server. Since I had some very bad experience performance-wise with OwnCloud on a Qnap-NAS (TS-219pII) and since the Raspberry Pi is no performance champ either, I've elected Seafile as my potential Dropbox-replacement. In fact, it's at least my fourth attempt to replace Dropbox: I also tried migrating to Bittorrent Sync (closed source *and* suspicious bugs *and* American...) and Syncthing (buggy, but promising), but both times I had mixed results.

Seafile development seems to progress rapidly and with the major version bump from 3.x to 4.x its internal architecture has changed noticeably. That's why I'm basing my installation (and documentation of it) on the official documentation and not on one of the many good but often dated guides I found online.

Here we go.

Seafile 4.2.3 on a Raspberry Pi

For some time now, there are offical server packages tailored specifically for the Raspberry. The project's "Manual" hyperlink leads directly to the instructions for an Sqlite-based setup. However, it is recommended to use MySQL when storing Seafile data on an external USB-disk. (This warning doesn't appear on the website, but it is shown by the setup script setup-seafile.sh.) I'm going to use the MySQL-server I configured a few days ago. (Just make sure you haven't disabled the InnoDB-engine to save a few KB of RAM.)

Step 1: Preliminaries

Make sure your mysql-server is up and running, then install some seafile-dependencies:

apt-get update
apt-get install python2.7 python-setuptools python-imaging python-mysqldb

Next, add a non-privileged user account. I'm using 1100 as uid in order to separate it from the regular uids 1000, 1001, ... that I might use later on to keep them in sync with my other computers.

adduser --home /mnt/usbdrive/seafile --uid 1100 seafile

Step 2: Download and set up

su seafile
cd
wget https://github.com/haiwen/seafile-rpi/releases/download/v4.2.3/seafile-server_4.2.3_pi.tar.gz
tar xzf seafile-server_4.2.3_pi.tar.gz 
cd seafile-server-4.2.3/
./setup-seafile-mysql.sh

The setup script is pretty self-explanatory. Here's a shortened version of its output (and my anonymized input):

What is the name of the server? It will be displayed on the client.
3 - 15 letters or digits
[ server name ] SomeName

What is the ip or domain of the server?
For example: www.mycompany.com, 192.168.1.101
[ This server's ip or domain ] seafile.example.org

Which port do you want to use for the ccnet server?
[ default "10001" ] 

Where do you want to put your seafile data?
Please use a volume with enough free space
[ default "/mnt/usbdrive/seafile/seafile-data" ] 

Which port do you want to use for the seafile server?
[ default "12001" ] 

Which port do you want to use for the seafile fileserver?
[ default "8082" ] 
-------------------------------------------------------
Please choose a way to initialize seafile databases:
-------------------------------------------------------
[1] Create new ccnet/seafile/seahub databases
[2] Use existing ccnet/seafile/seahub databases
[ 1 or 2 ] 1

What is the host of mysql server?
[ default "localhost" ] 

What is the port of mysql server?
[ default "3306" ] 

What is the password of the mysql root user?
[ root password ] ***************

Enter the name for mysql user of seafile. It would be created if not exists.
[ default "root" ] seafile

Enter the password for mysql user "seafile":
[ password for seafile ] 

Enter the database name for ccnet-server:
[ default "ccnet-db" ] 

Enter the database name for seafile-server:
[ default "seafile-db" ] 

Enter the database name for seahub:
[ default "seahub-db" ]

When the script is done, it prints a summary of the relevant commands and ports:

-----------------------------------------------------------------
Your seafile server configuration has been finished successfully.
-----------------------------------------------------------------

run seafile server:     ./seafile.sh { start | stop | restart }
run seahub  server:     ./seahub.sh  { start  | stop | restart  }

-----------------------------------------------------------------
If you are behind a firewall, remember to allow input/output of these tcp ports:
-----------------------------------------------------------------

port of ccnet server:         10001
port of seafile server:       12001
port of seafile fileserver:   8082
port of seahub:               8000

(These ports won't have to be forwarded or opened up for Internet-wide access. The final configuration will need exactly one open port: the default HTTPS-port: 443.)

Step 4: Check basic functionality

Your Seafile installation should now be ready for a (local) test drive. Just start it up by running

./seafile start
./seafile stop

from seafile's home directory (/mnt/usbdrive/seafile in the example). You can then access the SeaHub web-interface by visiting http://localipofyourserver:8000 in your browser. Obviously it's not recommended to make port 8000 internet-accessible. I'm using a LAN-connection to make a first connection. Later on, when everything is configured correctly, I'll forward port 443 in my router in order to sync files through HTTPS.

Anyway, it should now be possible to create an admin account and an unprivileged user account in SeaHub. Synchronizing through one of the clients should also be possible (using the local IP or local server name).

Step 5: nginx and HTTPS

By default, SeaHub runs on a simplistic python webserver called gunicorn. More flexibility (including SSL-support or IPv6-networking) can be achieved by using a proper webserver, i.e. nginx or apache. I'm opting for nginx with SSL. I won't enter in the details of creating a SSL-certificate. You can either follow one of the many tutorials on how to create a self-signed certificate or use a certificate issued by a recognized Certificate Authority. (I went with the latter, using a free(!) certificate provided by startssl.com. Here's an excellent and up-to-date guide explaining the setup.)

A requirement for this configuration is to apt-get install python-flup. Then I put the relevant nginx server blocks in place:

server {
    listen 80;
    server_name seafile.example.org;
    rewrite ^ https://$http_host$request_uri? permanent; # force redirect http to https
}

server {
    listen 443;
    ssl on;
    ssl_certificate     /etc/nginx/ssl/seafile.example.org-chain.pem;
    ssl_certificate_key /etc/nginx/ssl/seafile.example.org.key;

    server_name seafile.example.org;

    proxy_set_header X-Forwarded-For $remote_addr;

    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;

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

    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;
    }

    location /media {
        root /mnt/usbdrive/seafile/seafile-server-latest/seahub;
    }
}

Note that this setup is not IPv6-ready. The only reason I'm not setting up IPv6 is that I put my Raspberry Pi in a (very basic) DMZ using an older DD-WRT-equipped router. While Seafile itself (e.g. its built-in webserver, other internal components, etc.) is based on IPv4, the reverse-proxy setup with nginx should enable a flawless translation between external IPv6-traffic and the internal communication with the IPv4-loop-interface. To enable IPv6, it should be sufficient to add the relevant "listen" directives.

Before restarting Seahub using nginx, a few more configuration settings have to be made:

# in /mnt/usbdrive/seafile/ccnet/ccnet.conf
# modify the following value:
SERVICE_URL = https://seafile.example.org

# in /mnt/usbdrive/seafile/seahub_settings.py
# add the following line:
FILE_SERVER_ROOT = 'https://seafile.example.org/seafhttp'

Now it's time to check that everything's working.

cd /mnt/usbdrive/seafile/seafile-server-latest
# if seahub is still running, disable it first
./seahub.sh stop
./seahub.sh start-fastcgi
service nginx restart

Step 6: Start Seafile at startup

The final missing piece is to configure the init-system (sysv-rc, since Minibian/Raspbian wheezy is not yet systemd-based) to start Seafile at boot time. Here's the necessary init-script (adapted from the offical manual...)

#!/bin/sh

### BEGIN INIT INFO
# Provides:          seafile-server
# Required-Start:    $local_fs $remote_fs $network mysql
# 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 your linux user name
user=seafile

# Change the value of "script_path" to your path of seafile installation
# usually the home directory of $user
seafile_dir=/mnt/usbdrive/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)
                sudo -u ${user} ${script_path}/seafile.sh ${1} >> ${seafile_init_log}
                if [ $fastcgi = true ];
                then
                        sudo -u ${user} ${script_path}/seahub.sh ${1}-fastcgi ${fastcgi_port} >> ${seahub_init_log}
                else
                        sudo -u ${user} ${script_path}/seahub.sh ${1} >> ${seahub_init_log}
                fi
        ;;
        restart)
                sudo -u ${user} ${script_path}/seafile.sh ${1} >> ${seafile_init_log}
                if [ $fastcgi = true ];
                then
                        sudo -u ${user} ${script_path}/seahub.sh ${1}-fastcgi ${fastcgi_port} >> ${seahub_init_log}
                else
                        sudo -u ${user} ${script_path}/seahub.sh ${1} >> ${seahub_init_log}
                fi
        ;;
        stop)
                sudo -u ${user} ${script_path}/seahub.sh ${1} >> ${seahub_init_log}
                sudo -u ${user} ${script_path}/seafile.sh ${1} >> ${seafile_init_log}
        ;;
        *)
                echo "Usage: /etc/init.d/seafile-server {start|stop|restart}"
                exit 1
        ;;
esac

This file should be saved as /etc/initi.d/seafile-server. Here are the final steps to enable the init-script:

chmod +x /etc/init.d/seafile-server
mkdir /mnt/usbdrive/seafile/logs
chmod +x /etc/init.d/seafile-server
update-rc.d seafile-server defaults

Step 7: Test & enjoy

If anything doesn't work or doesn't seem right, feel free to let me know in the comments. A truly great source for help are the official community-forums.

Tags : seafileraspberrypinginxmysql

Copyright © 2015–2019 Hambier
GS RU