Skip to content

Commit

Permalink
Initial commit.
Browse files Browse the repository at this point in the history
  • Loading branch information
technomancy committed Apr 20, 2013
0 parents commit 47881eb
Show file tree
Hide file tree
Showing 20 changed files with 555 additions and 0 deletions.
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
.vagrant
tmp/
debian/*.debhelper.log
debian/cedar/
debian/files
debian/*.substvars
45 changes: 45 additions & 0 deletions Readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
Heroku Stack Images
=========

The provided bin/cedar.sh is the basis of a cedar stack image.

cd hvm
vagrant up
vagrant ssh

sudo /vagrant/bin/build-stack 2.0.0 /vagrant/bin/cedar.sh
-----> Starting build
-----> Installing build tools
Hit http://us.archive.ubuntu.com lucid Release.gpg
...
-----> Cleaning up. Logs in /tmp/log/build-stack.log

sudo /vagrant/bin/capture-stack 2.0.0
-----> Starting capture
-----> Creating image file /tmp/cedar64-2.0.0.img
24+0 records in
...
-----> Cleaning up. Logs in /tmp/log/capture-stack.log

sudo /vagrant/bin/install-stack /tmp/cedar64-2.0.0.img.gz
-----> Starting install
-----> Gunzipping image /tmp/cedar64-2.0.0.img.gz
-----> Mounting image /mnt/stacks/cedar64-2.0.0

Stack images are generally pushed to S3 and installed from there.

sudo /vagrant/bin/push-stack 2.0.0 stacks_bucket \
AWS_ACCESS_KEY_ID=xxx AWS_SECRET_ACCESS_KEY=xxx
-----> Starting push
-----> Uploading files
/tmp/cedar64-2.0.0.img.gz -> s3://stacks_bucket/cedar64-2.0.0.img.gz
...
-----> Signing URLs
http://s3.amazonaws.com/noah_herokustacks/cedar64-2.0.0.img.gz?AWS...
http://s3.amazonaws.com/noah_herokustacks/cedar64-2.0.0.img.md5

sudo /vagrant/bin/install-stack \
"http://s3.amazonaws.com/noah_herokustacks/cedar64-2.0.0.img.gz?AWS..."
-----> Starting install
-----> Downloading and gunzipping image
-----> Mounting image /mnt/stacks/cedar64-2.0.0
19 changes: 19 additions & 0 deletions Vagrantfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
Vagrant::Config.run do |config|
config.vm.box = "lucid64"
config.vm.box_url = "http://files.vagrantup.com/lucid64.box"
config.vm.network :hostonly, "33.33.33.3"
config.ssh.forward_agent = true
config.vm.share_folder("log", "/tmp/log", "tmp/log")

config.vm.provision :shell, :inline => <<-'EOSRC'
(
date
apt-get update
apt-get install -y curl git-core lxc s3cmd
mkdir -p /cgroup
mount none -t cgroup /cgroup
) 2>&1 | tee /tmp/log/provision.log
EOSRC
end
45 changes: 45 additions & 0 deletions bin/build-stack
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
#!/bin/bash
source $(dirname $0)/stack-helpers.sh
LOG=/tmp/log/$(basename $0).log
mkdir -p /tmp/log

(
[ $# -eq 2 ] || abort usage: $(basename $0) VERSION SCRIPT

VERSION=$1
SCRIPT=$2
MNT=/tmp/cedar64-$VERSION-build

[ $UID = 0 ] || abort fatal: must be called with sudo
[[ -f $SCRIPT ]] || abort fatal: script "$SCRIPT" not found
[[ -d $MNT ]] && abort fatal: dir "$MNT" already exists

function on_exit() {
display Cleaning up. Logs at $LOG
umount $MNT/dev $MNT/proc 2>&1 | indent
}
trap on_exit EXIT

display Starting build at $(date)
display Installing build tools
(
apt-get update
apt-get install -y build-essential debootstrap git-core
) 2>&1 | indent

display Bootstrapping build env $MNT
(
mkdir -p $MNT
debootstrap --variant=minbase lucid $MNT
) | indent

display Mounting host in build env
(
mount --bind /dev $MNT/dev
mount --bind /proc $MNT/proc
cp $SCRIPT $MNT/tmp/build.sh
) | indent

display Building inside build env
chroot $MNT /tmp/build.sh | indent
) 2>&1 | tee $LOG
81 changes: 81 additions & 0 deletions bin/capture-stack
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
#!/bin/bash
source $(dirname $0)/stack-helpers.sh
LOG=/tmp/log/$(basename $0).log

(
[ $# -ge 1 ] || abort usage: $(basename $0) VERSION [--no-gzip]

VERSION=$1
NOGZIP=$2
MNT=/tmp/cedar64-$VERSION-build
IMG=/tmp/cedar64-$VERSION.img
IMG_MNT=/tmp/cedar64-$VERSION

[ $UID = 0 ] || abort fatal: must be called with sudo
[[ -d $MNT ]] || abort fatal: dir "$MNT" not found

function on_exit() {
display Cleaning up. Logs at $LOG
( umount $IMG_MNT 2>&1 || true ) | indent
}
trap on_exit EXIT

display Starting capture at $(date)
display Creating image file $IMG
(
mkdir -p $(dirname $IMG)
dd if=/dev/zero of=$IMG bs=100M count=24
yes | mkfs -t ext3 -m 1 $IMG
tune2fs -c 9999 $IMG
tune2fs -i 9999w $IMG
) 2>&1 | indent

display Mounting image $IMG_MNT
mkdir -p $IMG_MNT
mount -o loop,noatime,nodiratime $IMG $IMG_MNT

display Copying stack to image
(
cd $MNT
rsync -a --exclude=/lib/modules bin etc lib lib64 sbin usr $IMG_MNT
rsync -a var/lib $IMG_MNT/var
) | indent

display Modifying image directories and files
(
for d in app tmp proc dev var var/log var/tmp home/group_home mnt/slug-compiler; do
mkdir -p $IMG_MNT/$d
done
chmod 755 $IMG_MNT/home/group_home

echo "127.0.0.1 localhost localhost.localdomain" > $IMG_MNT/etc/hosts

echo "heroku-runtime" > $IMG_MNT/etc/hostname

for f in etc/profile etc/bash.bashrc; do
echo "export PS1='\\[\\033[01;34m\\]\\w\\[\\033[00m\\] \\[\\033[01;32m\\]$ \\[\\033[00m\\]'" > $IMG_MNT/$f
done

cat >$IMG_MNT/etc/resolv.conf <<EOF
nameserver 172.16.0.23
domain z-2.compute-1.internal
search z-2.compute-1.internal
EOF

cat > $IMG_MNT/home/group_home/.gitconfig <<EOF
[user]
name = Heroku Git
email = [email protected]
EOF
chmod 644 $IMG_MNT/home/group_home/.gitconfig
) | indent

display Unmounting image
umount $IMG_MNT

display MD5ing and gzipping image
(
md5sum $IMG | cut -d ' ' -f 1 | tr -d '\n' | tee $IMG.md5
[[ -n $NOGZIP ]] || gzip $IMG
) | indent
) 2>&1 | tee $LOG
105 changes: 105 additions & 0 deletions bin/cedar.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
#!/bin/bash

exec 2>&1
set -e
set -x

cat > /etc/apt/sources.list <<EOF
deb http://archive.ubuntu.com/ubuntu lucid main
deb http://archive.ubuntu.com/ubuntu lucid-security main
deb http://archive.ubuntu.com/ubuntu lucid-updates main
deb http://archive.ubuntu.com/ubuntu lucid universe
EOF

apt-get update
apt-get install -y --force-yes language-pack-en
apt-get install -y --force-yes coreutils tar build-essential autoconf
apt-get install -y --force-yes libxslt-dev libxml2-dev libglib2.0-dev libbz2-dev libreadline5-dev zlib1g-dev libevent-dev libssl-dev libpq-dev libncurses5-dev libcurl4-openssl-dev libjpeg-dev libmysqlclient-dev
apt-get install -y --force-yes daemontools
apt-get install -y --force-yes curl netcat telnet
apt-get install -y --force-yes ed bison
apt-get install -y --force-yes strace gdb
apt-get install -y --force-yes openssh-client openssh-server
apt-get install -y --force-yes imagemagick libmagick9-dev
apt-get install -y --force-yes ia32-libs

cd /tmp
curl --retry 3 --max-time 60 --write-out %{http_code} --silent -o squashfs-tools_3.3-1ubuntu2_amd64.deb http://launchpadlibrarian.net/11397899/squashfs-tools_3.3-1ubuntu2_amd64.deb
dpkg -i squashfs-tools_3.3-1ubuntu2_amd64.deb

cd /tmp
curl -L -o git-1.7.0.tar.gz https://github.com/git/git/tarball/v1.7.0
mkdir -p git-1.7.0
cd git-1.7.0
tar --strip-components 1 -xzvf ../git-1.7.0.tar.gz
NO_EXPAT=yes NO_SVN_TESTS=yes NO_IPV6=yes NO_TCLTK=yes make prefix=/usr
NO_EXPAT=yes NO_SVN_TESTS=yes NO_IPV6=yes NO_TCLTK=yes make install prefix=/usr

apt-get install -y --force-yes openjdk-6-jdk openjdk-6-jre-headless

cd /tmp
curl -O "http://www.python.org/ftp/python/2.7.2/Python-2.7.2.tgz"
tar xfz Python-2.7.2.tgz
cd Python-2.7.2
./configure
make
make install

cd /tmp
curl -O http://ftp.ruby-lang.org/pub/ruby/1.9/ruby-1.9.2-p290.tar.gz
tar xzf ruby-1.9.2-p290.tar.gz
cd ruby-1.9.2-p290
./configure --prefix=/usr/local
make
make install

cd /tmp
curl -O "http://www.erlang.org/download/otp_src_R14B04.tar.gz"
tar xfz otp_src_R14B04.tar.gz
cd otp_src_R14B04
./configure
make
make install

# remove non-root owned artifacts of erlang
rm -rf /usr/local/lib/erlang/lib/sasl-2.1.10/examples/
rm -rf /usr/local/lib/erlang/lib/ssl-4.1.6/examples/
rm -rf /usr/local/lib/erlang/lib/kernel-2.14.5/examples/

cd /
rm -rf /var/cache/apt/archives/*.deb
rm -rf /root/*
rm -rf /tmp/*

# remove SUID and SGID flags from all binaries
function pruned_find() {
find / -type d \( -name dev -o -name proc \) -prune -o $@ -print
}

pruned_find -perm /u+s | xargs -r chmod u-s
pruned_find -perm /g+s | xargs -r chmod g-s

# remove non-root ownership of files
chown root:root /var/lib/libuuid

# display build summary
set +x
echo -e "\nRemaining suspicious security bits:"
(
pruned_find ! -user root
pruned_find -perm /u+s
pruned_find -perm /g+s
pruned_find -perm /+t
) | sed -u "s/^/ /"

echo -e "\nInstalled versions:"
(
git --version
java -version
ruby -v
gem -v
python -V
) | sed -u "s/^/ /"

echo -e "\nSuccess!"
exit 0
25 changes: 25 additions & 0 deletions bin/install-stack
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#!/bin/bash
source $(dirname $0)/stack-helpers.sh
LOG=/tmp/log/$(basename $0).log

(
[ $# -eq 1 ] || abort usage: $(basename $0) IMG_GZ \| URL

IMG_GZ=$1
MNT=/mnt/stacks/$(basename ${IMG_GZ%.img.gz*})

[ $UID = 0 ] || abort fatal: must be called with sudo

display Starting install at $(date)
if [[ -f $IMG_GZ ]]; then
display Gunzipping image $IMG_GZ
gunzip -c $IMG_GZ > $MNT.img
else
display Downloading and gunzipping image
curl $IMG_GZ | gunzip > $MNT.img
fi

display Mounting image $MNT
mkdir -p $MNT
mount -o loop,noatime,nodiratime,ro $MNT.img $MNT
) 2>&1 | tee $LOG
19 changes: 19 additions & 0 deletions bin/provision.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#!/bin/bash

function append_once() {
while read data; do
grep -q "$data" $1 || echo "$data" >> $1
done
}

apt-get update
apt-get -y --force-yes install curl git-core lxc

# mount cgroup for LXC
mkdir -p /cgroup
mount none -t cgroup /cgroup
append_once /etc/fstab <<EOF
none /cgroup cgroup defaults 0 0
EOF

# download or build a cedar image
Loading

0 comments on commit 47881eb

Please sign in to comment.