Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save newbamboo/90791 to your computer and use it in GitHub Desktop.
Save newbamboo/90791 to your computer and use it in GitHub Desktop.

Ubuntu 8.10 Intrepid 32-bit server AMI taken from (http://alestic.com/): ami-7cfd1a15

Useful guides:

Panda user

See this guide for details about securing an EC2 instance: http://developer.amazonwebservices.com/connect/entry!default.jspa?categoryID=100&externalID=1233&printable=true

Panda (the Merb application) will be run as the panda user on the system. To setup the user we first create them:

adduser panda

The password is set to panda123 (however we will disable password login in a moment).

Edit /etc/ssh/sshd_config and disable password login by ensuring these lines exist:

PasswordAuthentication no

Then restart ssh:

/etc/init.d/ssh restart

Now we'll make a copy of the EC2 script is run on startup and copies the key in your EC2 keychain to authorized_keys.

nano /etc/init.d/ec2-get-credentials-for-panda-user

The file should contain the following script:

#!/bin/bash
#
# ec2-get-credentials - Retrieve the ssh credentials and add to authorized_keys
#
# Based on /usr/local/sbin/ec2-get-credentials from Amazon's ami-20b65349
#

prog=$(basename $0)
logger="logger -t $prog"

public_key_url=http://169.254.169.254/1.0/meta-data/public-keys/0/openssh-key
public_key_file=/tmp/openssh_id.pub
public_key_ephemeral=/mnt/openssh_id.pub
authorized_keys=/home/panda/.ssh/authorized_keys

# Wait for the network to come up.
perl -MIO::Socket::INET -e '
 until(new IO::Socket::INET("169.254.169.254:80")){print"Waiting for network...\n";sleep 1}
' | $logger

# Try to get the ssh public key from instance data.
curl --silent --fail -o $public_key_file $public_key_url
test -d /home/panda/.ssh || mkdir -p -m 700 /home/panda/.ssh
if [ $? -eq 0 -a -e $public_key_file ] ; then
  if ! grep -s -q -f $public_key_file $authorized_keys
  then
    cat $public_key_file >> $authorized_keys
    $logger "New ssh key added to $authorized_keys from $public_key_url"
  fi
  chmod 600 $authorized_keys
  rm -f $public_key_file

# Try to get the ssh public key from ephemeral storage
elif [ -e $public_key_ephemeral ] ; then
  if ! grep -s -q -f $public_key_ephemeral $authorized_keys
  then
    cat $public_key_ephemeral >> $authorized_keys
    $logger "New ssh key added to $authorized_keys from $public_key_ephemeral"
  fi
  chmod 600 $authorized_keys
  chmod 600 $public_key_ephemeral
fi

chown -R panda:panda /home/panda/.ssh

Then we set this script to run on startup:

chmod +x /etc/init.d/ec2-get-credentials-for-panda-user
cd /etc/rc2.d
ln -s ../init.d/ec2-get-credentials-for-panda-user S69ec2-get-credentials-for-panda-user

Double check this works by running /etc/init.d/ec2-get-credentials-for-panda-user and sshing in with the panda user.

Deb sources

Add src repo to the source so we can compile ffmpeg from source. The /etc/apt/source.list should look like so:

deb http://ec2-us-east-mirror.rightscale.com/ubuntu intrepid main restricted universe multiverse
deb-src http://us.archive.ubuntu.com/ubuntu/ intrepid main restricted universe multiverse
deb http://ec2-us-east-mirror.rightscale.com/ubuntu intrepid-updates main restricted universe multiverse
deb-src http://us.archive.ubuntu.com/ubuntu/ intrepid-updates main restricted universe multiverse
deb http://security.ubuntu.com/ubuntu intrepid-security main restricted universe multiverse

Ruby

Ruby 1.8 is already installed.

apt-get update
apt-get install irb1.8 libreadline-ruby1.8 rdoc1.8 ri1.8 ruby1.8-dev

ln -s /usr/bin/ruby1.8 /usr/bin/ruby
ln -s /usr/bin/ri1.8 /usr/bin/ri
ln -s /usr/bin/rdoc1.8 /usr/bin/rdoc
ln -s /usr/bin/irb1.8 /usr/bin/irb

Rubygems

wget http://rubyforge.org/frs/download.php/45905/rubygems-1.3.1.tgz
tar xzvf rubygems-1.3.1.tgz
cd rubygems-1.3.1
ruby setup.rb
ln -s /usr/bin/gem1.8 /usr/bin/gem

MySQL

apt-get install mysql-client-5.0 mysql-common mysql-server-5.0 libmysqlclient15-dev

We'll also create the MySQL db panda as well:

mysqladmin -u root create panda

Other deps

apt-get install git-core unzip xfsprogs

Apache and Phusion Passenger

See: http://www.modrails.com/install.html

apt-get install apache2 apache2-prefork-dev

Using Passenger 2.1.1 (beta): http://blog.phusion.nl/2009/03/01/phusion-passenger-211-beta-released-thanks-sponsors/

wget http://phusion-passenger.googlecode.com/files/passenger-2.1.1.gem
gem install passenger-2.1.1.gem --no-rdoc --no-ri
passenger-install-apache2-module -a

Also get the upload progress module and compile as described here: http://drogomir.com/blog/2008/6/18/upload-progress-bar-with-mod_passenger-and-apache

Add the following config lines into /etc/apache2/httpd.conf:

LoadModule upload_progress_module /usr/lib/apache2/modules/mod_upload_progress.so
UploadProgressSharedMemorySize 1024000

LoadModule passenger_module /usr/lib/ruby/gems/1.8/gems/passenger-2.1.1/ext/apache2/mod_passenger.so
PassengerRoot /usr/lib/ruby/gems/1.8/gems/passenger-2.1.1
PassengerRuby /usr/bin/ruby1.8

Then add the site config to /etc/apache2/sites-available/panda:

<VirtualHost *:80>
    DocumentRoot /var/www/panda/current/public
    
    <Location />
        # enable tracking uploads in /
        TrackUploads On
    </Location>

    <Location /progress>
        # enable upload progress reports in /progress
        ReportUploads On
    </Location>
</VirtualHost>

Enable the site and disable the default site config:

rm /etc/apache2/sites-enabled/000-default
ln -s /etc/apache2/sites-available/panda /etc/apache2/sites-enabled/000-panda

We also must create the app's dir:

mkdir -p /var/www/panda /var/www/panda/releases /var/www/panda/shared /var/www/panda/shared/system /var/www/panda/shared/log /var/www/panda/shared/pids
chmod -R g+w /var/www/panda
chown -R panda:panda /var/www/panda

On Startup we will need to create a dir in /mnt for temporary video storage when encoding:

nano /etc/init.d/panda-create-tmp-store-dir

The script should contain the following:

#!/bin/bash
mkdir -p /mnt/panda/tmp
chown -R panda:panda /mnt/panda

Then enable it on startup:

chmod +x /etc/init.d/panda-create-tmp-store-dir
cd /etc/rc2.d
ln -s ../init.d/panda-create-tmp-store-dir S68panda-create-tmp-store-dir

EBS for MySQL storage

...

Panda encoder and notifier init scripts

Put this script into /usr/local/bin/panda_services (see Gist for revision history: http://gist.github.com/81885):

#!/bin/bash
# Startup script for a Panda encoder and notifier.

APPLICATION=$2
PORT=$3
MERB_ENV=$APPLICATION
MERB_RUNNER_FILE="bin/$APPLICATION.rb"
MERB_ROOT="/var/www/panda/current"
PID_FILE="$MERB_ROOT/log/merb.$APPLICATION.pid"
USER_AND_GROUP="panda"
RETVAL=0

# Go no further if merb app conf is gone
if [ ! -d "$MERB_ROOT/" ]; then
	echo "FATAL: $MERB_ROOT does not exist"
	exit 0
fi

start()
{
	echo -n "Starting Panda encoder:"

  cd $MERB_ROOT
	command="merb -u $USER_AND_GROUP -G $USER_AND_GROUP -n $APPLICATION.$PORT -e $MERB_ENV -P $PID_FILE -p $PORT -r $MERB_RUNNER_FILE -d";
	eval "$command";

	timeout=10
  while [ ! -f "$PID_FILE" ] ; do
    sleep 1
    timeout=$(( $timeout - 1 ))
    if [ $timeout -le 0 ] ; then
	    echo "                                            [ FAIL ]"
      echo "FATAL: master process did not drop a correct pid file within 10 seconds"
      exit 1
    fi
  done

  echo "                                            [  OK  ]"
  exit 0
}

stop()
{
  kill -s INT `cat $PID_FILE`
  RETVAL=$?
  echo -n "Stopping Panda encoder:"
  if [ "$RETVAL" -ne 0 ]
  then
    echo "                                            [ FAIL ]"
  else
    echo "                                            [  OK  ]"
  fi
}

case "$1" in
  start)
    start
    ;;
  stop)
    stop
    ;;
  restart)
    stop
    sleep 2
    start
    ;;
  *)
  echo "Usage: $0 (start|stop|restart) (encoder|notifier) <port>"
  exit $RETVAL
esac

Make it executable:

chmod +x /usr/local/bin/panda_services

God

gem install god --no-ri --no-rdoc

We'll setup God to monitor Panda's encoder and notifier processes.

Edit your /etc/god/panda_services.god to look like so:

{:encoder => 5000, :notifier => 6000}.each do |app, port|
  God.watch do |w|
    w.name = "#{app}-#{port}"
    w.interval = 20.seconds # default      
    w.start = "/usr/local/bin/panda_services start #{app} #{port}"
    w.stop = "/usr/local/bin/panda_services stop #{app}"
    w.restart = "/usr/local/bin/panda_services restart #{app}"
    w.start_grace = 10.seconds
    w.restart_grace = 10.seconds
    w.pid_file = "/var/www/panda/current/log/merb.#{app}.pid"

    w.behavior(:clean_pid_file)

    w.start_if do |start|
      start.condition(:process_running) do |c|
        c.interval = 5.seconds
        c.running = false
      end
    end
  end
end

Setup God to start on boot (source of script) by creating /etc/init.d/god:

#!/bin/sh

### BEGIN INIT INFO
# Provides:             god
# Required-Start:       $all
# Required-Stop:        $all
# Default-Start:        2 3 4 5
# Default-Stop:         0 1 6
# Short-Description:    God
### END INIT INFO

NAME=god
DESC=god

set -e

# Make sure the binary and the config file are present before proceeding
test -x /usr/bin/god || exit 0

# Create this file and put in a variable called GOD_CONFIG, pointing to
# your God configuration file
test -f /etc/default/god && . /etc/default/god
[ $GOD_CONFIG ] || exit 0

. /lib/lsb/init-functions

RETVAL=0

case "$1" in
  start)
    echo -n "Starting $DESC: "
    /usr/bin/god -c $GOD_CONFIG -P /var/run/god.pid -l /var/log/god.log
    RETVAL=$?
    echo "$NAME."
    ;;
  stop)
    echo -n "Stopping $DESC: "
    kill `cat /var/run/god.pid`
    RETVAL=$?
    echo "$NAME."
    ;;
  restart)
    echo -n "Restarting $DESC: "
    kill `cat /var/run/god.pid`
    /usr/bin/god -c $GOD_CONFIG -P /var/run/god.pid -l /var/log/god.log
    RETVAL=$?
    echo "$NAME."
    ;;
  status)
    /usr/bin/god status
    RETVAL=$?
    ;;
  *)
    echo "Usage: god {start|stop|restart|status}"
    exit 1
    ;;
esac

exit $RETVAL

Make executable and add to startup:

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

Then set the location of the God config file in /etc/default/god:

GOD_CONFIG=/etc/god/panda_services.god

TODO: Auto pull latest Panda and initial setup on first boot

Script should read EC2 user data to determine Panda github repo and branch to use.

PULL PANDA TO /var/www/panda/current
AUTOMIGRATE
SETUP DEFAULT USER LOGIN

cd /var/www/panda/current
merb -e production -r "User"

Install Panda dependencies

Next we follow the steps in the Local Installation Guide

Once complete we should have a nicely configured AMI which users can boot up, attach and EBS volume to and do a simple cap deploy from their local box to get Panda up and running.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment