Cookies and Capacitors

How to transform a stock PogoPlug into a lean, mean, Lighttpd + Chyrp + SQLite + Postfix serving machine

Friday, Feb 24, 2012, 06:49PM

After my recent dabackle with installing and coordinating completely non-common server software, I thought I'd take an hour or so to type this for those brave souls who wish to squeeze every drop of performance out of their brave, little machines. Once you install ArchLinux to your PogoPlug, I'll walk you through the steps to get the rest running smoothly.

Before we start, make sure you've got ArchLinux up and running on your PogoPlug. Be sure to update it with pacman -Syu and invoke /sbin/reboot.

Ok, now that Linux is up and running, time to handle the brass tax of things. Let's see what we need: we want Chyrp, which requires a database. MySQL is complete overkill for a personal blog (or nearly any blog, for that matter). We're going to substitute SQLite instead. SQLite is a file-based DB, so it doesn't store anything in hundreds of megabytes of RAM like MySQL does. Normally, this could be seen as a performance bottleneck. However, your boot disk is a USB flash drive, so latency is a non-issue (I compared holding my served files on disk vs. in /dev/shm for good measure, and there was hardly a difference). So, it's settled! We'll use SQLite to store Chyrp's data.

But Chyrp also requires PHP, so we'll have to install that too. And, as everyone knows, we won't be serving anything without a web server!

To keep things nice and light, we'll use Lighttpd. It's very lean and powerful. Sure, we could use Nginx instead, but Nginx has horrible support for virtual hosting, which is a feature that I use. You can always use Nginx, but its configuration won't be covered in this tutorial.

Last, but not least, what are you going to do if you forget the password to Chyrp? It would be nice to have a mailer installed, so we'll use postfix. It's proven awesome. [citation needed]

Install the software

To install these programs (and their dependencies), issue the following command as root. If you're not logged in as root, do an su root.

pacman -Sy fcgi libsasl lighttpd php php-cgi php-sqlite postfix sqlite3 udev-automount unzip

Now, to make sure postfix and lighttpd start with the server, add them to the DAEMONS=( * ) in /etc/rc.conf. The line should read as follows:

:::text
DAEMONS=(... postfix lighttpd)

Mail server configuration

With that taken care of, let's configure our mail server. I use Google Apps to handle my mail at davisremmel.com, so we're going to configure the server according to these instructions. Append the following to /etc/postfix/main.cf.

:::text
relayhost = [smtp.gmail.com]:587
smtp_sasl_auth_enable = yes
smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd
smtp_sasl_security_options = noanonymous
smtp_tls_CAfile = /etc/postfix/cacert.pem
smtp_use_tls = yes

Next, create the file /etc/postfix/sasl_passwd with the following contents (fill in your credentials, too):

:::text
[smtp.gmail.com]:587    user.name@gmail.com:password

Don't forget to chmod it:

chmod 400 /etc/postfix/sasl_passwd

We're almost there. Issue the following command:

postmap /etc/postfix/sasl_passwd

Lastly, copy a certificate over to authenticate our connection with Google's servers.

cat /etc/ssl/certs/Thawte_Premium_Server_CA.pem | sudo tee -a /etc/postfix/cacert.pem

Ok! That's it, our mail server is configured!

PHP configuration

PHP configuration is easy as pie. nano /etc/php/php.ini and uncomment the following extensions (remove the semicolon) to enable SQLite functionality:

:::text
;extension=pdo_sqlite.so
;extension=sqlite.so
;extension=sqlite3.so

That's it!

Web server (lighttpd) configuration

nano /etc/lighttpd/lighttpd.conf and fill it with this:

:::text
# Lighttpd config file
# Edit values to suit your needs
# Don't forget to change the last line

server.modules = ( "mod_fastcgi", "mod_magnet", "mod_access", "mod_accesslog", "mod_rewrite", )

server.port     = 80
server.username     = "http"
server.groupname    = "http"
server.document-root    = "/srv/http/"
server.errorlog     = "/var/log/lighttpd/error.log"
dir-listing.activate    = "disable"
index-file.names    = ( "index.html", "index.php" )
mimetype.assign     = (
  ".pdf"          =>      "application/pdf",
  ".sig"          =>      "application/pgp-signature",
  ".spl"          =>      "application/futuresplash",
  ".class"        =>      "application/octet-stream",
  ".ps"           =>      "application/postscript",
  ".torrent"      =>      "application/x-bittorrent",
  ".dvi"          =>      "application/x-dvi",
  ".gz"           =>      "application/x-gzip",
  ".pac"          =>      "application/x-ns-proxy-autoconfig",
  ".swf"          =>      "application/x-shockwave-flash",
  ".tar.gz"       =>      "application/x-tgz",
  ".tgz"          =>      "application/x-tgz",
  ".tar"          =>      "application/x-tar",
  ".zip"          =>      "application/zip",
  ".mp3"          =>      "audio/mpeg",
  ".m3u"          =>      "audio/x-mpegurl",
  ".wma"          =>      "audio/x-ms-wma",
  ".wax"          =>      "audio/x-ms-wax",
  ".ogg"          =>      "audio/x-wav",
  ".wav"          =>      "audio/x-wav",
  ".gif"          =>      "image/gif",
  ".jpg"          =>      "image/jpeg",
  ".jpeg"         =>      "image/jpeg",
  ".png"          =>      "image/png",
  ".xbm"          =>      "image/x-xbitmap",
  ".xpm"          =>      "image/x-xpixmap",
  ".xwd"          =>      "image/x-xwindowdump",
  ".css"          =>      "text/css",
  ".html"         =>      "text/html",
  ".htm"          =>      "text/html",
  ".js"           =>      "text/javascript",
  ".asc"          =>      "text/plain",
  ".c"            =>      "text/plain",
  ".conf"         =>      "text/plain",
  ".text"         =>      "text/plain",
  ".txt"          =>      "text/plain",
  ".dtd"          =>      "text/xml",
  ".xml"          =>      "text/xml",
  ".mpeg"         =>      "video/mpeg",
  ".mpg"          =>      "video/mpeg",
  ".mov"          =>      "video/quicktime",
  ".qt"           =>      "video/quicktime",
  ".avi"          =>      "video/x-msvideo",
  ".asf"          =>      "video/x-ms-asf",
  ".asx"          =>      "video/x-ms-asf",
  ".wmv"          =>      "video/x-ms-wmv",
  ".bz2"          =>      "application/x-bzip",
  ".tbz"          =>      "application/x-bzip-compressed-tar",
  ".tar.bz2"      =>      "application/x-bzip-compressed-tar" 
 )

include "fastcgi.conf"
include "[yoursite.com].conf" # Taylor this to your site's domain name

Do the same, making the file /etc/lighttpd/fastcgi.conf:

:::text
index-file.names += ( "index.php" )

fastcgi.server = (
    ".php" => (
      "localhost" => ( 
        "bin-path" => "/usr/bin/php-cgi",
        "socket" => "/var/run/lighttpd/php-fastcgi.sock",
        "max-procs" => 2,
        "bin-environment" => (
          "PHP_FCGI_CHILDREN" => "0",
        ),
        "broken-scriptfilename" => "enable"
      ))
)

and /etc/lighttpd/yoursite.com.conf:

:::text
$HTTP["host"] == "yoursite.com" {
    server.document-root = "/srv/http/yoursite.com/"
    index-file.names = ( "index.php" )
    url.access-deny = ( ".twig" )
}

To use pretty URLs (why wouldn't you want those?) follow the instructions in this thread That's the end of that, now our web server can serve happily and quickly!

For good measure, let's reboot now.

Installing Chyrp

Ok! Now we're on high grounds; let's install Chyrp. First, make a directory corresponding to your web site. mkdir /srv/http/yoursite.com. Then, cd to it.

We need to grab Chyrp's files. To do this, wget http://chyrp.net/releases/chyrp_v2.5b2.zip (as of this writing, v2.5b2 is the latest version). Unzip the files with unzip chyrp_v2.5b2.zip and give permissions of everything to the user http with chown -R http:http /srv/http/.

Now, head over to a web browser and go to http://yoursite.com/. You'll see Chyrp's installation page. On that page, fill in the following as shown, and the rest should be set to your own preference.

Adapter: SQLite 3
Host: localhost
Username: [blank]
Password: [blank]
Database: includes/chyrp.db
Table Prefix: [blank]

Click install, and head to the next step! If the install is failing for you, delete everything in /srv/http and start over with Installing Chyrp. SQLite isn't completely rock solid with Chyrp, yet, but the developers are working on its compatibility. Don't forget to remove install.php and chyrp_v2.5b2.zip.

The final tweaks

So your web server is running, mail server is ready to serve, and Chyrp is installed. Let's tweak some final settings to squeeze every drop of performance out of this puppy.

Log in to Chyrp, and head to the Admin page. From there, click the Settings tab, then the Route tab. Check "Clean URLs" and click Update. Yay, we have pretty URLs!

Ok, those are great, but we need faster page loads! Head over to the Extend tab and drag the Cacher vX module to the Enabled (green) side. Page caching reduces database queries by storing static pages, and refreshing those pages every so often. This results in much faster load times for the end-user, and decreases server load because pages don't need to be rendered for every user.

One more thing

What, you want more? Well, OK then! We can do more -- we can compress! Modern browsers accept compression encodings, like gzip, so we can reduce simple files by over 70%!

To enable this, edit /etc/lighttpd/lighttpd.conf and add "mod_compress" to the server.modules. Then, just before the include statements, add the following:

:::text
compress.cache-dir  = "/dev/shm/lighttpd_compress/"
compress.filetype   = ( "text/plain", "text/css", "text/xml", "text/javascript", "text/html", "application/javascript", )

This makes lighttpd store cached versions of static files in /dev/shm/lighttpd_compress/. /dev/shm is a mount point for shared memory. Anything residing in that directory is stored directly in RAM, thus access times are nearly instantaneous. This cache can grow stale, though, so it's important to clear it out every now and then. wget http://files.davisremmel.com/tutorials/lighttpd_chyrp_sqlite_config/lighttpd_clean.sh into /etc/cron.daily/ to do it automatically. Don't forget to chmod +x /etc/cron.daily/lighttpd_clean.sh to make it executable.

Wow, you're still here?

Fine then! Let's speed things up even more! Lighttpd only caches static web pages. What about those pesky dynamic pages, though? Well, let's have PHP compress those! Edit /etc/php/php.ini and change zlib.output_compression and zlib.output_handler to On. Save the file and close the editor, then restart lighttpd: rc.d restart lighttpd. There! Now dynamic content will also be compressed.

Are you not entertained?! That's it; I mean, really it. You've got Chyrp installed, you're givin'er all she's got, now get posting!