Wednesday, December 23, 2009

Installing Varnish 2.0.6 From Source On Ubuntu

It's a nice thing to get init scripts and startup variables set in an easy way.

Download, build package, install - easy peasy

sudo apt-get update
sudo apt-get install subversion autotools-dev automake1.9 libtool autoconf libncurses-dev xsltproc quilt debhelper
cd /tmp
sudo svn co http://www.varnish-cache.org/svn/tags/varnish-2.0.6
cd varnish-2.0.6/varnish-cache
sudo dpkg-buildpackage
cd ..
sudo dpkg -i libvarnish1_2.0.6-2_i386.deb
sudo dpkg -i varnish_2.0.6-2_i386.deb

To make varnish listen on port 80, edit the default config:
sudo nano /etc/default/varnish

I wanted to set it up to cache static files so to shrink headers I want to unset any extra cookies sendt in header
nano /etc/varnish/default.vcl
sub vcl_recv {
    unset req.http.cookie;
}

Monday, December 21, 2009

Installing MogileFS server from source on Ubuntu 8.04 LTS

Install dependencies:
sudo apt-get install libdbd-mysql-perl
cpan
install IO::AIO
install BSD::Resource

Download latest version from cpan repository at http://search.cpan.org/dist/mogilefs-server/ :
wget http://search.cpan.org/CPAN/authors/id/D/DO/DORMANDO/mogilefs-server-2.34.tar.gz

Unpack it:
tar xvf mogilefs-server-2.34.tar.gz

Compile and install
cd mogilefs-server-2.34
perl Makefile.PL && make && make install

Create configs:

For tracker

mkdir /etc/mogilefs
nano /etc/mogilefs/mogilefsd.conf

db_dsn = DBI:mysql:mogilefs:host=mogiledb.yourdomain.com;port=3306;mysql_connect_timeout=5;mysql_ssl=1;mysql_compression=1
db_user = mogile
db_pass = sekrit
conf_port = 7001
listener_jobs = 5
node_timeout = 5
rebalance_ignore_missing = 1

For mogstored
nano /etc/mogilefs/mogstored.conf

maxconns = 10000
httplisten = 0.0.0.0:7500
mgmtlisten = 0.0.0.0:7501
docroot = /var/mogdata

Create users and init scripts

For tracker

adduser mogilefsd
sudo nano /etc/default/mogilefsd
and input
#!/bin/sh
# Defaults for the mogilefsd package
MOGILEFSD_RUNASUSER=mogilefsd


sudo nano /etc/init.d/mogilefsd

Put this in there:

#! /bin/sh
### BEGIN INIT INFO
# Provides:          mogilefsd
# Required-Start:    $local_fs $remote_fs $network $syslog
# Required-Stop:     $local_fs $remote_fs $network $syslog
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: Start/Stop the mogilefsd daemon
# Description:       Start/Stop the mogilefsd daemon.
### END INIT INFO

# PATH should only include /usr/* if it runs after the mountnfs.sh script
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
DAEMON=/usr/local/bin/mogilefsd
NAME=mogilefsd
DESC=mogilefsd
DEFAULTS=/etc/default/$NAME
PIDFILE=/var/run/$NAME.pid
SCRIPTNAME=/etc/init.d/$NAME

# Exit if the package is not installed
[ -x "$DAEMON" ] || exit 0

# Read configuration variable file if it is present
if [ -r $DEFAULTS ] ; then

    . $DEFAULTS

    if [ -z "$MOGILEFSD_RUNASUSER" ]; then
        echo "Cannot determine user to run as, even though defaults file ($DEFAULTS) exists."
        echo "Please run dpkg-reconfigure $NAME to correct the problem."
        exit 0
    fi
else
    echo "Can't start $NAME. Defaults file ($DEFAULTS) doesn't exist."
    echo "Please run dpkg-reconfigure $NAME to correct the problem."
    exit 0
fi

# Load the VERBOSE setting and other rcS variables
. /lib/init/vars.sh

set -e

#
# Function that starts the daemon/service
#
do_start()
{
 if [ -e $PIDFILE ]
  then

  if [ -d /proc/`cat $PIDFILE`/ ]
  then

   echo "$NAME already running."
   exit 0;
  else
   rm -f $PIDFILE
  fi

 fi

 start-stop-daemon --start --quiet --exec $DAEMON --pidfile $PIDFILE -b -m --name $NAME --chuid $MOGILEFSD_RUNASUSER
}

#
# Function that stops the daemon/service
#
do_stop()
{
 start-stop-daemon --stop --quiet --oknodo --pidfile $PIDFILE --name $NAME --user $MOGILEFSD_RUNASUSER
 rm -f $PIDFILE
}

case "$1" in
  start)
 echo -n "Starting $DESC: "
 do_start
 echo "$NAME."
 ;;
  stop)
 echo -n "Stopping $DESC: "
 do_stop
 echo "$NAME."
 ;;

  restart|force-reload)
 #
 # If the "reload" option is implemented, move the "force-reload"
 # option to the "reload" entry above. If not, "force-reload" is
 # just the same as "restart".
 #
 echo -n "Restarting $DESC: "
 do_stop
 sleep 1
 do_start
 echo "$NAME."
 ;;
  *)
 #echo "Usage: $SCRIPTNAME {start|stop|restart|reload|force-reload}" >&2
 echo "Usage: $SCRIPTNAME {start|stop|restart|force-reload}" >&2
 exit 3
 ;;
esac

:

For mogstored

sudo adduser mogstored
sudo nano /etc/default/mogstored
and enter
#!/bin/sh
# Defaults for the mogstored package
MOGSTORED_RUNASUSER=mogstored

sudo nano /etc/init.d/mogstored

and put this in there:

#! /bin/sh
### BEGIN INIT INFO
# Provides:          mogstored
# Required-Start:    $local_fs $remote_fs $network $syslog
# Required-Stop:     $local_fs $remote_fs $network $syslog
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: Start/Stop the mogstored daemon
# Description:       Start/Stop the mogstored daemon.
### END INIT INFO

# PATH should only include /usr/* if it runs after the mountnfs.sh script
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
DAEMON=/usr/local/bin/mogstored
NAME=mogstored
DESC=mogstored
DEFAULTS=/etc/default/$NAME
PIDFILE=/var/run/$NAME.pid
SCRIPTNAME=/etc/init.d/$NAME

# Exit if the package is not installed
[ -x "$DAEMON" ] || exit 0

# Read configuration variable file if it is present
if [ -r $DEFAULTS ] ; then

    . $DEFAULTS

    if [ -z "$MOGSTORED_RUNASUSER" ]; then
        echo "Cannot determine user to run as, even though defaults file ($DEFAULTS) exists."
        echo "Please run dpkg-reconfigure $NAME to correct the problem."
        exit 0
    fi
else
    echo "Can't start $NAME. Defaults file ($DEFAULTS) doesn't exist."
    echo "Please run dpkg-reconfigure $NAME to correct the problem."
    exit 0
fi

# Load the VERBOSE setting and other rcS variables
. /lib/init/vars.sh

set -e

#
# Function that starts the daemon/service
#
do_start()
{
 if [ -e $PIDFILE ]
  then

  if [ -d /proc/`cat $PIDFILE`/ ]
  then

   echo "$NAME already running."
   exit 0;
  else
   rm -f $PIDFILE
  fi

 fi

 start-stop-daemon --start --quiet --exec $DAEMON --pidfile $PIDFILE -b -m --name $NAME --chuid $MOGSTORED_RUNASUSER
}

#
# Function that stops the daemon/service
#
do_stop()
{
 start-stop-daemon --stop --quiet --oknodo --pidfile $PIDFILE --name $NAME --user $MOGSTORED_RUNASUSER
 rm -f $PIDFILE
}

case "$1" in
  start)
 echo -n "Starting $DESC: "
 do_start
 echo "$NAME."
 ;;
  stop)
 echo -n "Stopping $DESC: "
 do_stop
 echo "$NAME."
 ;;

  restart|force-reload)
 #
 # If the "reload" option is implemented, move the "force-reload"
 # option to the "reload" entry above. If not, "force-reload" is
 # just the same as "restart".
 #
 echo -n "Restarting $DESC: "
 do_stop
 sleep 1
 do_start
 echo "$NAME."
 ;;
  *)
 #echo "Usage: $SCRIPTNAME {start|stop|restart|reload|force-reload}" >&2
 echo "Usage: $SCRIPTNAME {start|stop|restart|force-reload}" >&2
 exit 3
 ;;
esac

:

Make it executable, and enable it to run at boot:

sudo chmod +x /etc/init.d/mogilefsd
sudo chmod +x /etc/init.d/mogstored
sudo update-rc.d mogilefsd defaults 
sudo update-rc.d mogstored defaults 


You can install utils from cpan without much hassle:
install MogileFS::Utils

but to get mogstats working you need give it a separate config file:
cp /etc/mogilefs/mogilefsd.conf /etc/mogilefs/mogilefs.conf

Installing nginx with php5, mysql and rewrite on Ubuntu 8.04LTS

Installing nginx

Start off by getting the sourcecode from http://nginx.org/en/download.html

wget http://nginx.org/download/nginx-0.7.64.tar.gz

Extract it
tar xvf nginx-0.7.64.tar.gz

Install header rewrite, http cache modules dependency

sudo apt-get install libpcre3 libpcre3-dev libssl-dev

Configure, compile and install
cd nginx-0.7.64
./configure && make && make install

If you want to follow the ubuntu/debian style paths:
sudo ln -s /usr/local/nginx/conf /etc/nginx

And change config to include sites-enabled
sudo nano /etc/nginx/nginx.conf
Add this under http {} directive:
include /etc/nginx/sites-enabled/*;

Example config to serve static files:
mkdir /etc/nginx/sites-enabled
sudo nano /etc/nginx/sites-enabled/default

server {
        listen   8081;
        server_name localhost;
        set $myroot /var/www;

        # Base config
        root $myroot;
        location / {
                index  index.php index.html index.htm;
        }

        # Enable PHP
        location ~ \.php$ {
                root            $myroot;
                fastcgi_pass   127.0.0.1:9000;
                fastcgi_index  index.php;
                fastcgi_param  SCRIPT_FILENAME $document_root$fastcgi_script_name;
                include        /etc/nginx/fastcgi_params;
        }

        # If the file exists as a static file serve it directly without
        # running all the other rewite tests on it
        if (-f $request_filename) {
                break;
        }
}



To make nginx start at boottime, create an init.d script

sudo nano /etc/init.d/nginx

Init script I borrowed from: http://articles.slicehost.com/2008/5/13/ubuntu-hardy-adding-an-nginx-init-script
#! /bin/sh

### BEGIN INIT INFO
# Provides:          nginx
# Required-Start:    $all
# Required-Stop:     $all
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: starts the nginx web server
# Description:       starts nginx using start-stop-daemon
### END INIT INFO

PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
DAEMON=/usr/local/nginx/sbin/nginx
NAME=nginx
DESC=nginx

test -x $DAEMON || exit 0

# Include nginx defaults if available
if [ -f /etc/default/nginx ] ; then
        . /etc/default/nginx
fi

set -e

case "$1" in
  start)
        echo -n "Starting $DESC: "
        start-stop-daemon --start --quiet --pidfile /usr/local/nginx/logs/$NAME.pid \
                --exec $DAEMON -- $DAEMON_OPTS
        echo "$NAME."
        ;;
  stop)
        echo -n "Stopping $DESC: "
        start-stop-daemon --stop --quiet --pidfile /usr/local/nginx/logs/$NAME.pid \
                --exec $DAEMON
        echo "$NAME."
        ;;

  restart|force-reload)
        echo -n "Restarting $DESC: "
        start-stop-daemon --stop --quiet --pidfile \
                /usr/local/nginx/logs/$NAME.pid --exec $DAEMON
        sleep 1
        start-stop-daemon --start --quiet --pidfile \
                /usr/local/nginx/logs/$NAME.pid --exec $DAEMON -- $DAEMON_OPTS
        echo "$NAME."
        ;;
  reload)
      echo -n "Reloading $DESC configuration: "
      start-stop-daemon --stop --signal HUP --quiet --pidfile /usr/local/nginx/logs/$NAME.pid \
          --exec $DAEMON
      echo "$NAME."
      ;;
  *)
        N=/etc/init.d/$NAME
        echo "Usage: $N {start|stop|restart|reload|force-reload}" >&2
        exit 1
        ;;
esac

exit 0


and

chmod +x /etc/init.d/nginx
sudo update-rc.d nginx defaults

Installing php5 support

Install php5 with modules wanted
apt-get install php5-cgi php5-mysql php5-curl php5-gd php5-idn php-pear php5-imagick php5-imap php5-mcrypt php5-memcache php5-mhash php5-ming php5-pspell php5-recode php5-snmp php5-sqlite php5-tidy php5-xmlrpc php5-xsl

Set up FastCGI:

Install dependency
apt-get install libfcgi0ldbl

Paste the init script into
/etc/init.d/php-fastcgi

The init script: /etc/init.d/php-fastcgi
#! /bin/sh
### BEGIN INIT INFO
# Provides:          php-fastcgi
# Required-Start:    $all
# Required-Stop:     $all
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: Start and stop php-cgi in external FASTCGI mode
# Description:       Start and stop php-cgi in external FASTCGI mode
### END INIT INFO

# Author: Kurt Zankl <[EMAIL PROTECTED]>

# Do NOT "set -e"

PATH=/sbin:/usr/sbin:/bin:/usr/bin
DESC="php-cgi in external FASTCGI mode"
NAME=php-fastcgi
DAEMON=/usr/bin/php-cgi
PIDFILE=/var/run/$NAME.pid
SCRIPTNAME=/etc/init.d/$NAME
PHP_CONFIG_FILE=/etc/php5/cgi/php.ini

# Exit if the package is not installed
[ -x "$DAEMON" ] || exit 0

# Read configuration variable file if it is present
[ -r /etc/default/$NAME ] && . /etc/default/$NAME

# Load the VERBOSE setting and other rcS variables
. /lib/init/vars.sh

# Define LSB log_* functions.
# Depend on lsb-base (>= 3.0-6) to ensure that this file is present.
. /lib/lsb/init-functions

# If the daemon is not enabled, give the user a warning and then exit,
# unless we are stopping the daemon
if [ "$START" != "yes" -a "$1" != "stop" ]; then
        log_warning_msg "To enable $NAME, edit /etc/default/$NAME and set START=yes"
        exit 0
fi

# Process configuration
export PHP_FCGI_CHILDREN PHP_FCGI_MAX_REQUESTS
DAEMON_ARGS="-q -b $FCGI_HOST:$FCGI_PORT -c $PHP_CONFIG_FILE"

do_start()
{
        # Return
        #   0 if daemon has been started
        #   1 if daemon was already running
        #   2 if daemon could not be started
        start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON --test > /dev/null \
                || return 1
        start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON \
                --background --make-pidfile --chuid $EXEC_AS_USER --startas $DAEMON -- \
                $DAEMON_ARGS \
                || return 2
}

do_stop()
{
        # Return
        #   0 if daemon has been stopped
        #   1 if daemon was already stopped
        #   2 if daemon could not be stopped
        #   other if a failure occurred
        start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile $PIDFILE > /dev/null # --name $DAEMON
        RETVAL="$?"
        [ "$RETVAL" = 2 ] && return 2
        # Wait for children to finish too if this is a daemon that forks
        # and if the daemon is only ever run from this initscript.
        # If the above conditions are not satisfied then add some other code
        # that waits for the process to drop all resources that could be
        # needed by services started subsequently.  A last resort is to
        # sleep for some time.
        start-stop-daemon --stop --quiet --oknodo --retry=0/30/KILL/5 --exec $DAEMON
        [ "$?" = 2 ] && return 2
        # Many daemons don't delete their pidfiles when they exit.
        rm -f $PIDFILE
        return "$RETVAL"
}
case "$1" in
  start)
        [ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME"
        do_start
        case "$?" in
                0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
                2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
        esac
        ;;
  stop)
        [ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME"
        do_stop
        case "$?" in
                0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
                2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
        esac
        ;;
  restart|force-reload)
        log_daemon_msg "Restarting $DESC" "$NAME"
        do_stop
        case "$?" in
          0|1)
                do_start
                case "$?" in
                        0) log_end_msg 0 ;;
                        1) log_end_msg 1 ;; # Old process is still running
                        *) log_end_msg 1 ;; # Failed to start
                esac
                ;;
          *)
                # Failed to stop
                log_end_msg 1
                ;;
        esac
        ;;
  *)
        echo "Usage: $SCRIPTNAME {start|stop|restart|force-reload}" >&2
        exit 3
        ;;
esac

Install it
sudo chmod +x /etc/init.d/php-fastcgi
sudo update-rc.d php-fastcgi defaults 
Place the configuration for the script in
/etc/default/php-fastcgi

Config file for init script (the init script looks for this): /etc/default/php-fastcgi

START=yes

# Which user runs PHP? (default: www-data)

EXEC_AS_USER=www-data

# Host and TCP port for FASTCGI-Listener (default: localhost:9000)

FCGI_HOST=localhost
FCGI_PORT=9000

# Environment variables, which are processed by PHP

PHP_FCGI_CHILDREN=4
PHP_FCGI_MAX_REQUESTS=1000

Edit nginx config to make use of FastCGI
sudo nano /etc/nginx/nginx.conf
location ~ \.php$ {
  root           /var/www/nginx-default;
  fastcgi_pass   127.0.0.1:9000;
  fastcgi_index  index.php;
  fastcgi_param  SCRIPT_FILENAME    $document_root$fastcgi_script_name;
  include        /etc/nginx/fastcgi_params;
}


Config for fastcgi

/etc/nginx/fastcgi_params file
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  SCRIPT_NAME        $fastcgi_script_name;
fastcgi_param  REQUEST_URI        $request_uri;
fastcgi_param  DOCUMENT_URI       $document_uri;
fastcgi_param  DOCUMENT_ROOT      $document_root;
fastcgi_param  SERVER_PROTOCOL    $server_protocol;

fastcgi_param  GATEWAY_INTERFACE  CGI/1.1;
fastcgi_param  SERVER_SOFTWARE    nginx;

fastcgi_param  REMOTE_ADDR        $remote_addr;
fastcgi_param  REMOTE_PORT        $remote_port;
fastcgi_param  SERVER_ADDR        $server_addr;
fastcgi_param  SERVER_PORT        $server_port;
fastcgi_param  SERVER_NAME        $server_name;

# PHP only, required if PHP was built with --enable-force-cgi-redirect
fastcgi_param  REDIRECT_STATUS    200;


Setting up mod_rewrite and memcache

Uncomment to enable memcache
nano /etc/php5/conf.d/memcache.ini
and restart php-fastcgi to enable config
sudo /etc/init.d/php-fastcgi restart

To rewrite edit nginx config:
# assume a clean URL is requested, and rewrite to index.php                                                                
if (!-e $request_filename) {
  rewrite  ^/(.*)$  /index.php?q=$1  last;
  break;
}

Friday, December 4, 2009

Installing Varnish 2.0.4-5 on Ubuntu Hardy 8.04 LTS

*UPDATE

New and improved approach
apt-get update
apt-get install subversion autotools-dev automake1.9 libtool autoconf libncurses-dev xsltproc quilt debhelper
cd /tmp
svn co http://varnish.projects.linpro.no/svn/tags/varnish-2.0.6
cd varnish-2.0.6/varnish-cache
dpkg-buildpackage
cd ..
dpkg -i libvarnish1_2.0.6-2_i386.deb
 dpkg -i varnish_2.0.6-2_i386.deb


Unforunately this isn't as easy as it's supposed to be. I probably tried each component in this install three times each before finding a suitable codebase that actually compile and behave as advertised. As an example - the nagios plugin in varnish-tools folder failed to recognize -l which is the only logical way to use it in my option. And 2.0.5 src from sourceforge failed to compile in my system. But besides that, when it's all good it's good! :D

My (successful) steps are as follows:

Basic install

Find a suitable repository from http://packages.ubuntu.com/lucid/varnish and add to sources.list
sudo nano /etc/apt/sources.list
I used this one:
deb http://no.archive.ubuntu.com/ubuntu lucid main universe
Then update aptitude and install varnish from the repository
sudo apt-get update
sudo apt-get install varnish
Edit configuration file, you probably want it on port 80
sudo nano /etc/default/varnish
Set up configuration for backend nodes, examples for common issues can be found at http://varnish.projects.linpro.no/wiki/VCLExamples
sudo nano /etc/varnish/default.vcl

I also wanted varnish to serve up static files, including flv files for streaming so I added this to default.vlc:
sub vcl_recv {
 if (req.url ~ "\.(png|gif|jpg|ico|jpeg)$") {
    unset req.http.cookie;
  }
 if (req.url ~ "\.(flv)$|\?") {
   unset req.http.cookie;
   # Switch to pipe mode. Control will eventually pass to vcl_pipe
   pipe;
 }
}


Restart varnish to make use of your new config
sudo /etc/init.d/varnish restart
I had problems with varnishstat giving the error message: Cannot open /usr/local/var/varnish/dns.mydomain.com/_.vsl: No such file or directory

This was probably because I tried installing from source at first without much success

To fix it I had to point init script to another daemon path
sudo nano /etc/init.d/varnish
locate DAEMON=/usr/sbin/varnishd and change to
DAEMON=/usr/local/sbin/varnishd
and restart varnish
sudo /etc/init.d/varnish restart

Varnish Nagios plugin
Checkout nagios check util from svn:
svn co http://varnish.projects.linpro.no/svn/tags/nagios-varnish-plugin-1.0
Get dependencies
sudo apt-get install automake autoconf libtool
Compile it
cd nagios-varnish-plugin-1.0/
./autogen.sh
./configure && make && make install
Use it
/usr/local/libexec/check_varnish -l -c 30 -w 50
OK: 79 Cache hit ratio