I deploy Rails and Ruby projects using capistrano and I manage my source control with git. Git is most typically accessed with a ssh key and not username-password. There is a way to proxy your key through your deploy server making it possible for capistrano to retrieve the code from a 3rd party (gitub or gitorious or ssh-enabled git-server). It’s called ssh agent. Not many people use it but it’s super handy and comes built in to most flavs of Linux and OS X Leopard.
Assuming you have already put your desktop public key in the git server’s authorized keys or on github/gitorious you have put your ssh public key in your profile. What you do is this:
echo >$HOME/.ssh/config <<\EOF
Host *.mydeployservers.com
ForwardAgent yes
Host *.myotherdeployservers.com
ForwardAgent yes
Host *
ForwardAgent no
EOF
chmod -R go-rwsx $HOME/.ssh
Now SSH-Agent is setup to forward your keys through the deploy server and and you are ready to do some deploying. You may need to login to the deploy server once and try to login to the git server (github or the like) one time to accept the servers ssh key and stash in the deploy server/user’s local “known_hosts” file.
ssh myuser@mydelpoyserver.com
# (and from there)
ssh git@github.com
# the login will fail but the important part is accepting the server's ssh key
exit
Now back on your desktop you can now deploy from github or the like without “deploy keys”.
ssh-add ; #only need to do this once per login to your desktop
cap deploy

Posted on April 30th, 2008 by dysinger
Filed under: @work | 2 Comments »
I was playing around with Braid and Piston for Git and didn’t like either of them. I didn’t feel like Piston was ready for Git and Braid seemed to complex. I just wanted git subtrees. Braid is doing the same thing but with more code around it. I like simple. It actually turns out that Git has all the tools built in to do sub-tree merging and updating. It’s really easy with a few sake (or rake) tasks. I am using this on a rails project with more than a dozen plugins and vendor/rails.
Update 5/1: It seems braid has been updated recently with some more features. I still like this simple sake task approach better.
I updated the tasks to squash merge today. Update is below and on pastie.
#
# Git Sub-Trees (No you don't need Braid or Piston - just the 3 tasks below)
# http://rubyurl.com/BwnY < - Read about the technique vs submodules
#
# This works super good with Rails plugins or when you are actively working
# on two related projects.
#
# Add these tasks with:
# sake -i http://pastie.caboo.se/189942.rb
# -or-
# wget http://pastie.caboo.se/189942.rb
# -or-
# curl -O http://pastie.caboo.se/189942.rb
# # edit edit edit
# sake -i 189942.rb
#
# Example Usage:
#
# sake git:subtree:remote
# Git Repo Url? git://github.com/mislav/will_paginate.git
# Remote Name? will_paginate
# sake git:subtree:add
# Branch? will_paginate/tags/2.2.2
# Destination? vendor/plugins/will_paginate
# git commit -m 'merged in new 2.2.2 will_paginate'
#
# Frome time to time update your remotes:
# git remote update
# -or-
# git fetch will_paginate ; # !NEW TAG SPOTTED!
#
# sake git:subtree:update
# Branch? will_paginate/tags/2.2.3
# git commit -m 'merged in new 2.2.3 will_paginate'
desc 'Add an external project as a remote'
task 'git:subtree:remote' do
require "readline"
url = begin
print "Git Repo Url? "
Readline.readline.chomp
end
name = begin
print "Remote Name? "
Readline.readline.chomp
end
`git remote add #{name} #{url}`
`git config remote.#{name}.fetch refs/heads/*:refs/remotes/#{name}/*`
`git config --add remote.#{name}.fetch refs/tags/*:refs/remotes/#{name}/tags/*`
`git config remote.#{name}.tagopt --no-tags`
`git fetch #{name}`
end
desc 'Merge an external project as a sub-tree'
task 'git:subtree:merge' do
require "readline"
branch = begin
print "Branch? "
Readline.readline.chomp
end
dest = begin
print "Destination? "
Readline.readline.chomp
end
`git merge --squash -s ours --no-commit #{branch}`
`git read-tree --prefix=#{dest} -u #{branch}`
end
desc 'Update an existing subtree project'
task 'git:subtree:update' do
require "readline"
branch = begin
print "Branch? "
Readline.readline.chomp
end
`git merge --squash -s subtree --no-commit #{branch}`
end
Posted on April 29th, 2008 by dysinger
Filed under: @work | 6 Comments »
I have prepared a new Ubuntu Hardy Amazon AMI image(s). They are in my ubuntu-ami bucket. I’ll start with a “small” ec2 instance image. The public AMI is “ami-4f7a9f26″. It is meant to be started with AKI “aki-9b00e5f2″ (which comes with fuse). The image is a bare-bones ubuntu hardy standard install. You can update it with the software you need. I will have 64-bit versions available early next week. The emphasis on my images is clean and tidy. I don’t install a bunch of crud that you may or may not need. It’s just the basics with a userdata-boot-hook (give the image a bash script at boot-time as userdata).
Here is how I created the image:
# Bootstrap
mkdir /mnt/ubuntu
debootstrap --arch i386 hardy /mnt/ubuntu
# Start
cat /proc/mounts >/mnt/ubuntu/etc/mtab
mount -o rbind /proc /mnt/ubuntu/proc
mount -o rbind /dev /mnt/ubuntu/dev
mount -o rbind /sys /mnt/ubuntu/sys
cat /etc/resolv.conf >/mnt/ubuntu/etc/resolv.conf
chroot /mnt/ubuntu /bin/bash
# Hostname
echo '127.0.0.1 localhost' >/etc/hosts
# Tidy
rm -rf tmp && ln -sf var/tmp tmp
rm -rf opt && ln -sf usr/local opt
# Locale
localedef -i en_US -c -f UTF-8 en_US.UTF-8
echo 'LANG="en_US.UTF-8"' >/etc/default/locale
# Update
cat >/etc/apt/sources.list < <\EOF
deb http://us.archive.ubuntu.com/ubuntu hardy main restricted universe multiverse
deb-src http://us.archive.ubuntu.com/ubuntu hardy main restricted universe multiverse
deb http://us.archive.ubuntu.com/ubuntu hardy-updates main restricted universe multiverse
deb-src http://us.archive.ubuntu.com/ubuntu hardy-updates main restricted universe multiverse
deb http://security.ubuntu.com/ubuntu hardy-security main restricted universe multiverse
deb-src http://security.ubuntu.com/ubuntu hardy-security main restricted universe multiverse
EOF
gpg --keyserver wwwkeys.pgp.net --recv-keys A70DAF536070D3A1
gpg --armor --export A70DAF536070D3A1 | apt-key add -
cat >/etc/apt/sources.list.d/debian.list < <\EOF
deb http://http.us.debian.org/debian/ unstable main contrib non-free
deb-src http://http.us.debian.org/debian/ unstable main contrib non-free
deb http://http.us.debian.org/debian/ experimental main contrib non-free
deb-src http://http.us.debian.org/debian/ experimental main contrib non-free
EOF
cat >/etc/apt/apt.conf < <\EOF
APT::Default-Release "hardy";
EOF
apt-get update
apt-get install -y libc6-xen
rm -rf /lib/tls
apt-get upgrade -y
apt-get install -y ubuntu-standard
# Modules
wget -O - \
http://s3.amazonaws.com/ec2-downloads/ec2-modules-2.6.18-xenU-ec2-v1.0-i686.tgz | \
tar --no-same-owner -xzC /
depmod -a
echo 'loop' >>/etc/modules
# Color
perl -p -i -e ’s/xterm-color/xterm\*color/g’ /etc/skel/.bashrc ~/.bashrc
apt-get install -y ncurses-term
# TTY
rm -f /etc/event.d/tty[2-6]
# Network
shadowconfig on
usermod -p \
`dd if=/dev/urandom count=50 2> /dev/null | md5sum | cut -d ” ” -f1-1` \
root
mkdir /etc/skel/.ssh
chmod 600 /etc/skel/.ssh
cp -r /etc/skel/.ssh /root
apt-get install -y ntp openssh-server
cat >/etc/ssh/sshd_config < <\EOF
Protocol 2
StrictModes yes
MaxStartups 10:30:60
Ciphers aes256-cbc,aes256-ctr
PasswordAuthentication no
ChallengeResponseAuthentication no
Subsystem sftp /usr/lib/openssh/sftp-server
UseDNS no
EOF
cat >/etc/network/interfaces < <\EOF
auto lo
iface lo inet loopback
auto eth0
iface eth0 inet dhcp
EOF
# Boot
cat >/etc/rc.local < <\EOF
#!/bin/sh -e
# Root SSH Public Key
mkdir -p /root/.ssh >/dev/null 2>&1
wget -q -O - http://169.254.169.254/2008-02-01/meta-data/public-keys/0/openssh-key \
>/root/.ssh/authorized_keys
chmod -R go-rwsx /root
# Userdata Shell Script
wget -q -O - http://169.254.169.254/2008-02-01/user-data | sh
exit 0
EOF
# Fstab
cat >/etc/fstab < <\EOF
/dev/sda1 / ext3 user_xattr 0 1
/dev/sda2 /mnt ext3 user_xattr 0 2
/dev/sda3 swap swap sw 0 0
EOF
# EC2 tools
apt-get install -y symlinks unzip ruby libopenssl-ruby1.8 curl ca-certificates
cd /tmp
wget http://s3.amazonaws.com/ec2-downloads/ec2-ami-tools.zip
cd /usr/local
unzip /tmp/ec2-ami-tools.zip
ln -sf `find . -type d -name ec2-ami-tools*` ec2-ami-tools
chmod -R go-rwsx ec2*
rm -rf /tmp/ec2*
# Bundle
rm /bin/sh && ln -s /bin/bash /bin/sh ; # make bash the default for ec2
modprobe loop ; # bundle image needs this
cat >/usr/local/sbin/image < <\EOF
#!/bin/bash
export EC2_AMITOOL_HOME=/usr/local/ec2-ami-tools
PATH=$EC2_AMITOOL_HOME/bin:$PATH
BUNDLE=`date '+%y%m%d%H%M%S'`
ec2-bundle-vol -r i386 -u $AMAZON_USER_ID --fstab /etc/fstab \
-k $EC2_PRIVATE_KEY -c $EC2_CERT -b -d /mnt -s 10240 -e /root/.ssh -p $BUNDLE
ec2-upload-bundle -b $HOSTNAME -m /mnt/$BUNDLE.manifest.xml \
-a $AMAZON_ACCESS_KEY_ID -s $AMAZON_SECRET_ACCESS_KEY
rm -rf /mnt/$BUNDLE* /mnt/img-mnt
EOF
chmod 700 /usr/local/sbin/image
export HOSTNAME=ubuntu-ami
apt-get clean
apt-get autoclean
apt-get autoremove
symlinks -cdrsv /
rm -rf /var/tmp/* ~/.bash_history
image
# Register & make the ami public (on another machine)
ec2-register $HOSTNAME/XXXXXXXXXXXXX.manifest.xml
ec2-modify-image-attribute ami-XXXXXXX --launch-permission -a all
# Run
ec2-run-instances \
-K ~/.amazon/pk.pem -C ~/.amazon/cert.pem \
-k mykey --kernel aki-9b00e5f2 \
ami-XXXXXXXXXXX
Posted on April 27th, 2008 by dysinger
Filed under: @work | No Comments »
Kids amaze me. Here’s a video of Dmitri Gaskin giving a Google Tech Talk on JQuery. Good job Dmitri! You remind me of myself when I was 12 except, when I was a kid, 6502 assembly language and Commodore’s where the in thing for kids and not web-programming.
The only problem I have with Dmitri is that he likes PHP and Drupal. He’s only 12 though. He’ll grow out of it… 
Posted on April 25th, 2008 by dysinger
Filed under: @home | 1 Comment »
In today’s ruby web application landscape, every framework developer is writing his/her own handlers for every server he/she wants to support. This results in semi-duplicate code, if not for the web-server developer then for the framework-developer. This is the pain-point that Rack aims to solve. Rack proposes “why not have some common ground?” Java did this with the Servlet API 10 years ago. Python did this with WSGI 5 years ago.
By leveraging Rack, framework developers and web-server developers gain access to one another without having to write special adapters. Today that’s WEBrick, Mongrel, CGI, Ebb, Fuzed & Thin for web-servers and Rails, Camping, Coset, Halcyon, Maveric, Merb, Racktools::SimpleApplication, Ramaze, Sinatra & Vintage for web-frameworks. (this will undoubtably be outdated by conference time). Tomorrow every new web-server and web-framework that supports Rack can be used together. You’ll be able to pick and choose the best web-server for you without changing your favorite web-framework and vice-versa.
“What do Rails developers really stand to gain today by leveraging Rack?” It might be the ability to run several “rackable” applications side by side inside a single web-server instance. It might be the possibility to leverage or stack applications. You can intercept requests, modify them and pass them through to other handlers. You can also have multiple rackable applications sitting next to each other that comprise one user-facing application. Don’t like file uploads with Rails? Use another web framework or the Rack API directly to write it and place it along side your Rails app in the same application. Want to use single-sign-on for 3 Rails apps? No problem. Rack makes it easy to tie apps together.
Rack Hello World ( gem install rack & mongrel & visit http://localhost:3000 )
%w(rubygems rack).each { |dep| require dep }
Rack::Handler::Mongrel.run(
lambda { |e| [
301,
{ ‘Location’ => ‘http://rubyurl.com/g6L’ },
’:P’
]
},
:Port => 3000
)
Posted on April 25th, 2008 by dysinger
Filed under: @work | No Comments »
I work in software development and it is a very competitive business. At times I have to catch myself, when I feel an emotion, and ask myself “Why?”. Why am I being competitive? Why am I seeking recognition? Why am I wanting control? Is my argument on the design the best for the team? Are my motivations the best for the project?
In reading about Karma Yoga, I realize that this is exactly what software developers need to do when writing software. Karma Yoga means “discipline of action” and is based on the teachings of the Bhagwat Geeta, a sacred Sanskrit scripture of Hinduism.
Karma Yoga is described as a way of acting, thinking and willing by which one does one’s duty without consideration of personal selfish desires, likes or dislikes. Acting without being attached to the fruits of one’s deeds. In software this is doing what needs to be done for the betterment of the project and team without attaching your ego and self-worth to the code you write or the contribution you make.
When this mindset is taken on by software developers, colloboration, camaraderie and team-work increases while tensions, egos, stress, competition and caustic attitudes decrease. It has to be consciencely chosen, but this is something to be strived for on teams.
Posted on April 22nd, 2008 by dysinger
Filed under: @work | No Comments »
I downloaded and gave VirtualBox a twirl this week. For those of you who haven’t heard of it, VirtualBox is a drop-in free and open source replacement for VMWare Fusion or Parallels. Did I mention it’s open source and free? Here’s the subversion repository.
Update 4/24/2008: I purchased VMWare Fusion last year and my rebate check never came. Peter contacted me and made sure my rebate was on the way. There’s nothing wrong with VMWare. It’s a fine tool. I just always have a leaning towards open source where ever possible.
Posted on April 18th, 2008 by dysinger
Filed under: @work | 1 Comment »
Phusion Passenger ( mod_rails ) is out so I thought I would give it a twirl. The mod_rails site has some install notes but it doesn’t go far enough. However, once you do the install and get used to it, it is a rather friendly setup. I can see it being a big boost to rails shared-hosting. The rails instances are scaled up and down on the fly behind apache so no static pre-configured pools of mongrel with monit watching them needed. Here’s how I got it going on the mac:
cd /tmp
curl ftp://ftp.oregonstate.edu/pub/apache/httpd/httpd-2.2.8.tar.gz | tar xz
cd httpd*
./configure
make
sudo make install
export APXS2=/usr/local/apache2
export PATH=/usr/local/apache2/bin:$PATH
sudo gem install passenger
sudo passenger-install-apache2-module
sudo chgrp -R admin /usr/local/apache2/conf
sudo chmod -R g+w /usr/local/apache2/conf
sudo chmod 2775 /usr/local/apache2/conf /usr/local/apache2/conf/extra
echo "Include conf/extra/httpd-rails.conf" >> /usr/local/apache2/conf/httpd.conf
cat >/usr/local/apache2/conf/extra/httpd-rails.conf <<\EOF
LoadModule passenger_module /Library/Ruby/Gems/1.8/gems/passenger-1.0.1/ext/apache2/mod_passenger.so
RailsSpawnServer /Library/Ruby/Gems/1.8/gems/passenger-1.0.1/bin/passenger-spawn-server
RailsRuby /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/bin/ruby
NameVirtualHost *
<VirtualHost *>
ServerName www.myapp.com
RailsEnv development
DocumentRoot /Users/tim/Projects/website/public
<Directory /Users/tim/Projects/website/public>
Allow from all
<Directory>
<VirtualHost>
EOF
sudo /usr/local/apache2/bin/apachectl start
exit
That’s it. You can see that you can add more <VirtualHost *> entries for other applications. You need to put www.myapp.com hostname on the end of the “localhost” line in /etc/hosts.
Posted on April 14th, 2008 by dysinger
Filed under: @work | No Comments »
I wanted to try out stacked git for maintaining patches. Here is how I did it on my mac.
git clone http://homepage.ntlworld.com/cmarinas/stgit.git
cd stgit
git checkout -b stable origin/stable
sudo python setup.py install --prefix=/usr/local
Here is some resources to get started using stacked git.
Posted on April 5th, 2008 by dysinger
Filed under: @work | No Comments »
JRuby, the awesome Java meets Ruby project, has been released and tagged as 1.1. This is really good news. Thanks should be patted on the backs of each JRuby developer for this milestone. If you haven’t checked JRuby out, now is the time.
Here is the announcement http://docs.codehaus.org/display/JRUBY/2008/04/05/JRuby+1.1+Released
Posted on April 5th, 2008 by dysinger
Filed under: @work | No Comments »