Wednesday, 20 April 2011

Development and build environments: schroot on openSUSE -- part 2

So in part 1 I detailed my search for something that would allow my development and productive environments to coexist on the same machine, and how I discovered schroot.

Schroot is a "chroot manager" - it allows configuring chroots so that users on the system can run shells and processes in them, and it takes care of all the setup/tear down I described at the end of my previous post. It is a part of the Debian buildtools, for building Debian packages in a safe and repeatable environment, just like openSUSE uses build.

Advantages of using schroot to setup development environments
Vs Full Virtualization:
  • low hardware requirements
  • easy network setup (just copy /etc/resolv.conf into the chroot)
  • can run X apps directly into running host X display
  • easy to share - host always has access to all guest files
  • can just run out of a directory
Vs plain chroots
  • can easily setup multiple environments
  • can run out of disk images or actual devices
  • takes care of all the setup work
  • manages sessions
  • good cleanup of any leftover processes and mounts on exit
Disadvantages of chroots vs full Virtualization
  • No real process isolation - no difference between a process inside the chroot and outside the chroot. Even 'ps' shows processes both inside and outside the chroot (/proc is shared)
  • No real security - trivial for a malicious program to break out of a chroot, full host hardware access by mounting all of /dev (unless you spend the time to only allow through specific devices)
  • OS is never actually booted (no init) or shutdown, just specific processes run, so harder to run daemons

First step was packaging schroot, no problem there, except that it doesn't seem to exist anywhere except in the Debian package system. I just grabbed the source from their source dpkg. I found that flichtenheld also had schroot packaged in his home project on OBS, so I grabbed some patches that looked useful (thanks!). The package is currently in my home project, it's been SR'ed to devel:tools, but is also waiting on a security review (since it runs setuid)

Next was configuring it. Read the schroot manpages, they are quite complete. schroot comes with three chroot types: default, desktop, and minimal. Since I wanted to run X apps, I used the desktop type, with a few modifications. All you have to do is create a configuration file in /etc/schroot/chroot.d/. For example, here's my development environment.

[devel]
type=directory
description=Development 11.4 installation
groups=wheel
root-groups=wheel
script-config=desktop/config
directory=/home/chroot

Note that I've allowed anyone in the "wheel" group (just me atm) to use this chroot, as a user or as root.

Then I setup the directory /home/chroot. Zypper has a very nice feature that allows bootstrapping openSUSE installs in situations like this: the "-R, --root" option where zypper behaves as if that is the root directory.

#first add a repository - I had my 11.4 dvd handy so I decided to save some bandwidth
sudo zypper -R /home/chroot ar dvd:///
#then install needed packages. base or minimal_base pattern is a good idea. sw_management installs zypper
sudo zypper -R /home/chroot in -t pattern base sw_management

Now you can chroot in with
schroot -c devel

A nice chroot is all set up for you, you can do your work, and when you leave it's all cleaned up. I was quickly able to run X apps, screen, and all my development tools - so far I've been able to do everything I need to. Excellent!

Schroot also comes with some pretty cool support for LVM and brtfs-based chroots - it can automatically create temporary sessions based off a "source chroot", which I thought was pretty cool and might use that in the future.

schroot is quite an extensible program; for example, it runs the scripts it finds in /etc/schroot/setup.d/ to create the chroots - you can easily add to this. I added tweaks to change the bash prompt so I know I'm in a chroot, allow ssh-agent access from the chroot, setup X11 authorizations properly to run X apps, and allow 'screen' usage.

If you want dbus system bus to work in your chroot, add to /etc/schroot/desktop/fstab
/var/run/dbus   /var/run/dbus   none    rw,bind         0       0
I also commented out /home since I didn't want my home dir shared into the chroot.

In /etc/schroot/desktop/config, I added these lines to give some config values to my custom script:
#Environment variables and values to copy over
ENVVARS="DISPLAY=:0"

#Display to extract authorization from
DISPLAY_AUTH=":0"

And I created the file below that is run every time a chroot is setup by schroot. Note it runs as root, outside the chroot. Anything that needs to be setup inside the chroot can be done via for example /etc/bash.bashrc.local, as I do for setting the prompt below. The variables used are all documented in the schroot man pages.
/etc/schroot/setup.d/75setupsuse contents:
#!/bin/sh
# Copyright © 2011 Tejas Guruswamy <tejas.guruswamy@opensuse.org>
#
# schroot is free software: you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# schroot is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see
# <http://www.gnu.org/licenses>.
#
#####################################################################

set -e

. "$SETUP_DATA_DIR/common-data"
. "$SETUP_DATA_DIR/common-functions"

if [ -f "$CHROOT_SCRIPT_CONFIG" ]; then
    . "$CHROOT_SCRIPT_CONFIG"
elif [ "$STATUS" = "ok" ]; then
    fatal "script-config file '$CHROOT_SCRIPT_CONFIG' does not exist"
fi

if [ $STAGE = "setup-start" ] || [ $STAGE = "setup-recover" ]; then

  info "Setting chroot environment and display"

  info "Grabbing .Xauthority from ${AUTH_USER} $DISPLAY_AUTH"
  su ${AUTH_RUSER} -c "xauth -f /home/${AUTH_RUSER}/.Xauthority extract ${CHROOT_PATH}/home/${AUTH_USER}/.Xauthority $DISPLAY_AUTH"

  info "Finding running ssh-agent"
SSH_AUTH_SOCK=$(find /tmp -user ${AUTH_RUSER} -name "agent*")
SSH_AGENT_PID=$(pidof ssh-agent)

  info "Adding ssh-agent variables to environment"
ENVVARS="SSH_AGENT_PID=$SSH_AGENT_PID SSH_AUTH_SOCK=$SSH_AUTH_SOCK $ENVVARS"

  vars=''
  for var in $ENVVARS; do
    info "export $var"
    vars=$(echo -e "$vars\nexport $var")
  done

  info "Setting chroot bash prompt"
  cat >"${CHROOT_PATH}/etc/bash.bashrc.local" <<'EOF'
if [ -z "$debian_chroot" ] && [ -r /etc/debian_chroot ]; then
debian_chroot=$(cat /etc/debian_chroot)
fi 
PS1="${debian_chroot:+($debian_chroot)}$PS1"
EOF

  echo "$vars" >> "${CHROOT_PATH}/etc/bash.bashrc.local"

  info "Creating temporary directories necessary for screen"
  mkdir -m 0755 ${CHROOT_PATH}/var/run/screens
  mkdir -m 1777 ${CHROOT_PATH}/var/run/uscreens

fi

if [ $STAGE = "setup-stop" ]; then

  rm -f ${CHROOT_PATH}/home/${AUTH_USER}/.Xauthority
# rm -f ${CHROOT_PATH}/etc/bash.bashrc.local
  rm -rf ${CHROOT_PATH}/var/run/screens
  rm -rf ${CHROOT_PATH}/var/run/uscreens

fi

No comments:

Post a Comment

Creative Commons Licence
This work by Tejas Guruswamy is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.