Monday, August 10, 2015

Raspberry Pi as a Seafile server

My latest Raspberry Pi project is to create a personal Seafile server.  If you've never heard of Seafile before you're probably not alone.  There are a lot of "cloud" based file backup and synchronization services like Dropbox, Google Drive, and Microsoft OneDrive.  These services are great and have many uses, but they have drawbacks as well.  They all offer free accounts so long as you stay under a certain size (usually around 5GB).  There's also the issue of security.  My data is being sent from my computer over the Internet to their servers, and then back.  But how secure is this?  Is the communication between my computer and their servers secure?  Once my data is on their servers, how secure is it?  If someone hacks in can they access my data?  Can the company hosting my data access it?  And what about government agencies, do they have a backdoor into these companies servers?

There are two free open-source alternatives; Seafile and Owncloud.  Owncloud is more well-known than Seafile, but every review I read online says that Owncloud is buggy whereas Seafile is rock solid.  I also really like Seafile's security model.  My data is encrypted on my computer using a password of my choosing and strong AES-256 encryption before the data is transmitted to Seafile.  What's more, the data is only decrypted on my device after downloading from Seafile.  In otherwords my password is never transmitted to Seafile which means hackers, Seafile themselves, and the NSA cannot access my data.

Because of this, years ago I signed up for a free Seafile account and I have grown to love it!  Unfortunately Seafile has a very low limit, only 1 GB at the time I signed up.  This isn't enough to effectively backup to, but I have used it for years as a sync point.  I have two computers at home and one at work and this makes a great place to put documents and files I want synchronized across all machines.  But I wanted more storage so I decided to create my own Seafile server at home.

Before I start my guide a few points:
  • I will be setting up a Seafile server with nginx as the web server, HTTPS for the communications, and SQLite as the back-end database.  This arrangement is a great combo for a single user or a small number of users.
  • There are a number of existing guides on how to do this.  Here's a great guide, this one is in German, and the official Seafile manual has generic Linux instructions.  But I found problems with each of these guides, things like missing steps.  So I combined all these into a single end-to-end guide to get this working.
  • I assume you know at least some Linux.  I'm not going to explain how to use tools like nano.  If you've never used Linux before then this entire process is probably over your head.  But if you know at least a little bit about Linux you should be good to go.
  • You should know how to SSH into a Linux system.  Most of the following is done while connected to the Raspberry Pi via an SSH connection.
  • I will be setting up my Seafile server for access both inside and outside my home network.  For this to work you'll need a DDNS account.  There are a number of both free and paid DDNS services.



Hardware:
For this project obviously you'll need a Raspberry Pi.  I used a Raspberry Pi B+.  But this would work with any Raspberry Pi.  In fact, this would be a perfect use for a model A since you won't need a lot of USB and the extra power savings means less electricty.  For the power supply I went with this one which I've used on previous Pi projects.  The 2amp supply will be overkill for this project, but it's a known good supply.  I decided to try a new case and went with this one.  I got the Edimax EW-7811Un wifi dongle.  I would have preferred to hard wire it, but my wireless router is out of empty ports so I went wireless.  And since this will be low-bandwidth it won't matter.  To complete the hardware I went with a 32GB Samsung EVO micro SD card.  This card will hold both the OS and the Seafile data.



Software:
On the software side of things I used Raspbian (version 2015-05-05).  You will also need Seafile itself.  I used version 4.2.3 which was the latest version at the time I did this.  You'll need a DDNS service, which I use the free service offered by my Synology NAS.


Guide:
Buckle in and get ready, this is going to be a long bumpy ride.

1.  Download Raspbian and use Win32 Disk Imager to copy into the SD card.
2.  Boot the Pi for the first time.  When the Raspbian config screen comes up, make the following changes:

  2a.  Select "Internationalization Options" and then "Change locale."  Place a check by "en_US.UTF-8 UTF-8."
  2b.  Select "Internationalization Options" and then "Change time zone."  Linux handles time zones differently than Windows.  Instead of selecting your time zone by name or UTC offset, you instead select a region and a city near you.  So for me I select Americas and Los Angeles.
  2c.  Select "Internationalization Options" and then "Change keyboard layout."  For me I selected "Generic 104 key" and "English US."  This step is important as the default keyboard layout is English UK with things like the pound sterling symbol.
  2d.  Select "Advanced Options" and then "Overscan."  Set this option to disabled.  Older analog TVs have overscan where the image is smaller than what the TV can display.  If I do not disable overscan then on my computer monitor I have half an inch of black all the way around the outside edge.  Disabling overscan corrects this.

  2e.  Select the option to resize the image then let the Pi reboot and resize.

The next step is to configure WiFi.  There is no doubt a terminal way to do this.  But I'm lazy and don't know how to do that in Linux, so I use the GUI to make it easy.



3.  Run "startx" then bring up a Terminal window from the start menu.  Run "wpa_gui" and connect to your wifi.

Now let's update the system and install Samba which makes networking much easier:

4.  sudo apt-get update
5.  sudo apt-get dist-upgrade
6.  sudo apt-get install samba samba-common-bin

Now let's change the computer's name.  I choose "seafilepi" as my computer name.

7.  Run "sudo nano /etc/hosts" and change raspberrypi to your new computer name.
8.  Run "sudo nano /etc/hostname" and change raspberrypi to your new computer name.
9.  Shut the system down with the command "sudo shutdown -h now"

The Raspberry Pi doesn't have much memory to begin with.  Since this is a headless unit let's make some changes to maximize memory usage.

10.  Put the SD card back into a Windows PC and edit the file config.txt.  Add the line "gpu_mem_512=16"  Note: this setting will disable the HDMI output.  If you still want HDMI then user 32 as the memory setting.
11.  Put the SD card back into the Pi and boot up.  Run "sudo nano /etc/inittab" then scroll down and use a '#' to comment out all "getty" lines.

Again, this will be a headless unit, so let's remove the unnecessary bits of Linux, like the graphical desktop X.  There's probably a better way to do this but this is what worked for me.  Note the first line actually removes too much, the second line adds some modules back in without which the Raspberry Pi would not have network access.

12.  sudo apt-get autoremove --purge libx11-.* fonts-.* desktop-.* lxde-.* epiphany-.* lightdm-.* alsa-.* gnome-.* raspberrypi-artwork xkb-data omxplayer penguinspuzzle sgml-base xml-core minecraft-pi sonic-pi wolfram-engine
13.  sudo apt-get install raspberrypi-net-mods
14.  sudo apt-get install deborphan
15.  sudo apt-get autoremove --purge $(deborphan)
16.  sudo apt-get autoremove --purge deborphan dialog
17.  sudo apt-get autoremove --purge
18.  sudo apt-get autoclean

When all is said and done this will take away about 1 - 1.5 GB of files.  So that 32GB SD card will have about 30 -31 GB of free space for Seafile.

Now we're ready to install Seafile itself.  First create a new user account under which Seafile will run.

19.  Run "sudo adduser seafile --disabled-password"  Enter the name as "seafile" and all other fields blank.

20.  sudo apt-get install python2.7 python-setuptools python-imaging sqlite3
21.  sudo su seafile
22.  cd ~
23.  mkdir cloud
24.  cd cloud
25.  wget https://github.com/haiwen/seafile-rpi/releases/download/v4.2.3/seafile-server_4.2.3_pi.tar.gz
26.  tar -xvzf seafile-server_4.2.3_x86-64.tar.gz
27.  mkdir installed
28.  mv seafile-server_* installed

The following commands will configure Seafile.  For the name choose the name of this server, something short like your name.  For IP address enter the computer name from steps 7 and 8.  All other fields use the default values.

29.  cd seafile-server_4.2.3
30.  ./setup-seafile.sh

We're now ready to start Seafile for the first time.  When you start the Seahub you'll be prompted for the administrator username and password.

31.  ./seafile.sh start
32.  ./seahub.sh start

33.  exit

At this point if you open a web browser and navigate to "http://seafilepi:8000" you should see the Seafile login screen.  If not you did something wrong so double-check your work to this point.  You could stop at this point and use Seafile.  But I want to go further and configure HTTPS for greater security, which requires nginx.

34.  sudo apt-get install nginx python-flup

nginx is not designed for the low resources found on the Pi, so let's make some changes to improve things.

35.  sudo nano /etc/nginx/nginx.conf


Change "worker_processes" from 4 to 1 (or 2 for Pi model 2).  Also change "worker_connections" from 768 to 128.  Save the changes and exit.

36.  sudo /etc/init.d/nginx start

37.  sudo su seafile
38.  cd ~/cloud
39.  Run "nano ccnet/ccnet.conf"  Change it to read SERVICE_URL = https://seafilepi:8001

40.  Run "nano seahub_settings.py"  Append the line  FILE_SERVER_ROOT = 'https://seafilepi:8001/seafhttp'

Let's stop and restart Seafile.

41.  cd seafile-server-latest
42.  ./seahub.sh stop
43.  ./seafile.sh stop
44.  ./seafile.sh start
45.  ./seahub.sh start-fastcgi
46.  exit

Now we need to create a self-signed digital certificate for nginx.  The second to the last command will prompt for a country code ("US" for United States), and your state.  For organization enter "None" and all other fields can be left blank.

47.  sudo mkdir /etc/nginx/ssl
48.  cd /etc/nginx/ssl

49.  sudo openssl genrsa -out seahub.key 4096
50.  sudo openssl req -new -key seahub.key -out seahub.csr

51.  sudo openssl x509 -req -days 3650 -in seahub.csr -signkey seahub.key -out seahub.crt
  Enter the following into the file /etc/nginx/sites-available/seahub and save it.

52.  sudo nano /etc/nginx/sites-available/seahub
server {
    listen 8001;
    ssl on;
    ssl_certificate /etc/nginx/ssl/seahub.crt;
    ssl_certificate_key /etc/nginx/ssl/seahub.key;
    server_name seafilepi;
    error_page 497 https://$host:$server_port$request_uri;

    client_max_body_size 0;

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

    location /media {
        root /home/seafile/cloud/seafile-server-latest/seahub;
        # include /etc/nginx/mime.types; # <--- UNCOMMENT THIS IF CSS FILES AREN'T LOADED
    }
}
53.  sudo ln -s /etc/nginx/sites-available/seahub /etc/nginx/sites-enabled/seahub
Now we can configure Seafile to autostart every time the Raspberry Pi is booted.  Enter the following into the file /etc/init.d/seafile-server and save it.

54.  sudo nano /etc/init.d/seafile-server
#!/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 your linux user name
user=seafile

# Change the value of "script_path" to your path of seafile installation
seafile_dir=/home/seafile/cloud
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

# Write a log message with date and time
echo -e "About to perform $1 for seafile at `date -Iseconds`" >> ${seafile_init_log}
echo -e "About to perform $1 for seahub at `date -Iseconds`" >> ${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 >> ${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 >> ${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

55.  sudo chmod +x /etc/init.d/seafile-server
56.  sudo update-rc.d seafile-server defaults
57.  sudo reboot

If you've done everything correctly, when the Rapberry Pi reboots you should be able to login using the URL https://seafilepi:8001  You'll get a warning about an untrusted certificate.  You can ignore this, it's because you used a self-signed certificate which is unknown to your web browser.

Next download and install the Seafile client for your device(s).  When you run Seafile you'll be prompted for a server address.  If the device will ever only access Seafile from inside your home network, you can enter the address of "https://seafilepi:8001"  However, if the device will access Seafile from outside your home network, then enter the address of "https://myddns.com:8001" where "myddns.com" is the DDNS for your home network.

As this point you're almost done.  The last step is to connect to your wireless router and enable port forwarding.  You must forward TCP port 8001 to the Raspberry Pi.  I can't tell you how to do this because every router is different.  But once you complete these step you should be able to sync to/from your personal Seafile server both inside and outside your home network.  Enjoy and good luck!

Wednesday, August 5, 2015

Water saving - the results

I recently posted about California's latest drought and water usage.  In that series I mentioned two simple changes I made at home to save water, I installed High Sierra low-flow shower heads and the HydroRight dual-flush toilet conversion kit.  It has been several months since I installed those products so I wanted to report back on how much water we are saving.

  • In the 6 months before installing these products, my family used an average of 173 gallons of water per day.
  • In the 3 months after installing these products, my family used an average of 115 gallons of water per day.
  • That's an average savings of 58 gallons of water per day.

Saving 58 gallons of water per day may not sound like a lot, but it adds up quickly.  Over a year we'll save approximately 21,000 gallons of water.  That's more water than an average-sized backyard swimming pool.

Here is a graph showing our water usage over the past 9 months.  As you can see the first 6 months are clearly higher than the last 3 months.

As far as cost savings, we saved an average of $11.85 on our monthly water bill.  The new shower heads and toilet products cost about $160 to install them in my house.  At that rate it will take 13 months to break even, and after that we'll save about $140 a year.


There were a couple of details about my water bill and usage that are worth mentioning.  Anyone who knows about water usage knows that 115 gallons of water per day for 4 people is extremely low.  That's an average of less than 30 gallons per person per day, but most places use between 100 and 200 gallons of water per person per day.  So how is ours so low?  There are two reasons.
  1. The biggest reason is the fact we don't have to water our landscaping which is the single largest use of water for a typical home.  In our neighborhood our landscaping and yards are watered by the HOA, so that watering goes on their water meter and not mine.  On the plus side, our neighborhood uses reclaimed water for landscaping so we're not wasting good water just to have a green lawn.
  2. My family has always been good about saving water, even before installing these products.  For example, we never took long showers and we didn't always flush the toilet for just liquids (as the saying goes - "If it's yellow, let it mellow. If it's brown, flush it down").

When I started this endeavor I wasn't sure how much water we would save.  I knew we were frugal with our water to begin with so I wasn't expecting much.  But to save almost 60 gallons of water per day definitely exceeded my expectations.  I hope that seeing our results has encouraged you to try water saving in your house.