RasPi lighttpd and server tweaks

This blog is hosted on a Raspberry Pi using the lighttpd (lighty) webserver. Since I haven’t been satisfied with the response time until a page is loaded, I applied some tweaks to increase its performance.

If you need details about your RasPi server, you can test it’s performance with Google’s online PageSpeed Insight tool. Then, follow the recommendations of the analysis results.

Most important for a good WordPress performance appears to be  CSS and Javascript concatenation/compression as well as installation of a cache plugin, such as Autoptimize and WP-Cache.com.

/boot/cmdline.txt, /etc/fstab

Although I use an “ultra” Sony Class 10 (94 MB/s) SD card, performance of the ext4 journaling file system has been an issue. To increase file system throughput, I added:

rootflags=commit=120,data=writeback

to /etc/cmdline.txt, and:

/dev/mmcblk0p2  /  ext4  defaults,noatime,nodiratime,barrier=0

to /etc/fstab. These options disable storing of access times to the file system. Using data=writeback mode extends the time from when a file is written to when it is pushed out to disk to 120 seconds. Be aware that you’ll lose all cached data on a file system crash!

/etc/sysctl.conf

To tell the system to use less IO/RAM, I placed these options into my /etc/sysctl.conf

vm.dirty_background_ratio = 20
vm.dirty_expire_centisecs = 0
vm.dirty_ratio = 80
vm.dirty_writeback_centisecs = 1200
vm.overcommit_ratio = 2
vm.laptop_mode = 5
vm.swappiness = 10

/etc/lighttpd/lighttpd.conf

Disabling keep-alive might help lighttpd if it suffers from a large number of open file descriptors. Select an event handler which takes care of notifying the server that one of the connections is ready to send or receive.

Since we want to send out a file from the webserver, it doesn’t make any sense to copy the file into the webserver just to write it back into a socket in the next step. Therefore, we enable linux-sendfile to minimize the work in the application and push the file directly into the network card.

With the help of gamin (sudo apt-get install gamin) you can use kernel events to assure that your stat cache is up to date.

server.max-keep-alive-requests = 0
server.event-handler = "linux-sysepoll"
server.network-backend = "linux-sendfile"
server.max-fds = 1024
server.stat-cache-engine = "fam"
server.max-worker = 0

After applying these tweaks, lighty responds much faster and I observed less “The site could be temporarily unavailable or too busy. Try again in a few moments.” messages.

Adding podcasts to MPD using castget

In order to play mp3 files on my RasPi, I’ve installed the Music Player Daemon (MPD). Music playback can be controlled with Mozilla Firefox using the Minion plugin. By placing *.m3u files into MPDs’ playlists folder, as configured in /etc/mpd.conf, it is possible to listen to internet radio streams.

Unfortunately, subscription to podcasts is not directly supported by MPD. However there’s a way to automatically download podcasts to MPD’s mp3 directory using a program called castget. It’s not in the Wheezy repo. Thus, it must be compiled from source:

$ ./configure --prefix=/usr
$ make
$ make install

To build castget, make sure to have the glib2, libxml2, libcurl and id3lib development packages installed on your Pi. Castget is using a default ./castgetrc in /home/pi for configuration, but one can point it to a different location by using the –rcfile=/etc/castgetrc flag. The castget tarball provides a sample configuration file.

# Global settings.
[*]
id3contenttype=Podcast
spool=/media/usb/podcasts

# Per-channel settings.
[dsc]
url=http://www.deutschlandfunk.de/podcast-computer-und-kommunikation-komplette-sendung.416.de.podcast.xml
playlist=/var/lib/mpd/playlists/Computer_u_Kommunikation.m3u

[dsc]
url=http://www.deutschlandradiokultur.de/podcast-reportage.948.de.podcast.xml
playlist=/var/lib/mpd/playlists/Deutschland_Reportage.m3u

All you need to do is to define a spool directory for downloading the podcasts, to enter the URLs of the podcast’s RSS feeds and to tell castget where to store the playlist.m3u files (must be the the same directory as defined in /etc/mpd.conf).

To automatically check and download new podcasts each 24 hours at 02:00 am, I placed a new line into my /etc/crontab

 0  2    * * *   root    /usr/bin/castget -r --rcfile=/etc/castgetrc

If the download was successful, new podcasts should appear in Minion’s playlists tab.

Dynamic webcam control (update)

Several weeks of testing revealed that my Python script for time-dependent webcam control works quite reliable. However, there were a few over-/or underexposed images close to sunset or sunrise. Turning off auto-exposure during daytime helped to prevent overexposed pictures, especially on bright and sunny days.

These fixed exposure settings resulted in too dark images on rainy and cloudy days. Since most webcams are optimized for indoor use, it is safe to use auto-exposure settings under these weather conditions. But how to let a script decide about that? For this purpose, I adopted the ImageStat function of the Python Imageprocessing Library (PIL), which allows to calculate an average arbitrary value for brightness. If it drops below a certain threshold level, auto-exposure settings are activated. Before calculation of brightness, the image is converted to gray-scale. The whole operation is done in memory, without the need to save a temporary file to disk.

Dynamic webcam control using (py)ephem

Time-dependent webcam control

For taking still images with a webcam looking outside my sleeping room window, I’ve attached a Logitech C510 to my RasPi. At first, I used the fswebcam program to acquire still images, which can be easily configured using a fswebcam.conf file as follows:

quiet device v4l2:/dev/video0
input 0
skip 50
palette MJPEG
background
resolution 1600x1200
set "White Balance Temperature, Auto"=1
set "Exposure, Auto"=3
set "Backlight Compensation"=1
#set "sharpness"=100
#set "gain"=0{c7f7cb1468c0d02af358b3ce02b96b7aadc0ce32ccb53258bc8958c0e25c05c4}
#set "exposure"=1
#set "brightness"=35{c7f7cb1468c0d02af358b3ce02b96b7aadc0ce32ccb53258bc8958c0e25c05c4}
#set "contrast"=10{c7f7cb1468c0d02af358b3ce02b96b7aadc0ce32ccb53258bc8958c0e25c05c4}
#set "saturation"=60
#set hue=10
#top-banner
#font /usr/share/fonts/truetype/msttcorefonts/arial.ttf
title "RasPi-Cam"
timestamp "{c7f7cb1468c0d02af358b3ce02b96b7aadc0ce32ccb53258bc8958c0e25c05c4}d-{c7f7cb1468c0d02af358b3ce02b96b7aadc0ce32ccb53258bc8958c0e25c05c4}m-{c7f7cb1468c0d02af358b3ce02b96b7aadc0ce32ccb53258bc8958c0e25c05c4}Y {c7f7cb1468c0d02af358b3ce02b96b7aadc0ce32ccb53258bc8958c0e25c05c4}H:{c7f7cb1468c0d02af358b3ce02b96b7aadc0ce32ccb53258bc8958c0e25c05c4}M:{c7f7cb1468c0d02af358b3ce02b96b7aadc0ce32ccb53258bc8958c0e25c05c4}S ({c7f7cb1468c0d02af358b3ce02b96b7aadc0ce32ccb53258bc8958c0e25c05c4}Z)"
jpeg 50
save /var/www/data/snaps/snap.jpg

Some settings required careful tweaking, since most webcams are optimized for indoor use. Although the settings above resulted in pictures of reasonable quality, I noticed that they were pretty much overexposed on bright sunny days. And they were far too dark at night. It turned out that the auto exposure function of my webcam is unable to deal with changing light conditions.

Therefore I did some research on how to change the settings dynamically, depending on time of day. It turned out to be a simple task using some python scripting.