+title: Cross-Building Haskell Programs using LXC
+date: September 19, 2012
+One of the benifits of Haskell is that compiled Haskell programs can be run on any computer, even
+computers without any Haskell packages installed. For this to work the version of libc and various
+helper libraries like zlib must match between the build machine and the target machine, so for
+deployment between similar distribution versions one can just compile right on the develop machine
+and deploy. Unfortunately, if you are like me and want to deploy code to a server running 32-bit
+Debian stable and your development machine is 64-bit Ubuntu 12.04, you need a way of compiling
+32-bit Haskell programs on the Ubuntu machine.
+After some work, I was able to get [virthualenv](http://hackage.haskell.org/package/virthualenv) on
+my development machine to cross-compile using a downloaded i386 binary ghc (this used the recent
+multiarch support in Debian and Ubuntu). This worked and produced 32-bit Haskell programs and
+simple programs worked fine, unfortunately the version of zlib did not match so running more
+complicated programs on Debian would exit with an error. (The changes to get virthualenv + i386 ghc
+working were mostly to tell ghc to pass "-m32" to gcc.) Because of the library version issue, I
+decided to investigate instead using containers to run a copy of Debian on my Ubuntu development
+machine. The default container technology in Ubuntu 12.04 is [LXC](http://lxc.sourceforge.net/), so
+# An LXC container with the latest GHC
+I suggest you first read [this documentation](https://help.ubuntu.com/12.04/serverguide/lxc.html) on
+LXC in Ubuntu. A word of warning, LXC had several significant changes in Ubuntu 12.04 so if you do
+a google search for LXC and Ubuntu you get a lot of outdated information. I was tripped up by this
+initially, instead I suggest you stick to the Ubuntu document linked above, it is way easier than a
+lot of tutorials I found in a google search.
+To install LXC, just apt-get install lxc. I didn't need to do any configuration beyond that. Next,
+we need to edit the debian template to specify the arch. The ubuntu templates support specifying
+the arch on the command line, but unfortunately the debian templates in 12.04 don't. (This might
+change in future versions, so if you are reading this much after September 2012 you should check out
+the options.) In any case, edit /usr/lib/lxc/templates/lxc-debian and go to around line 191. After
+the code checking architecture, I just added a line 'arch="i386"' to force i386 arch.
+Next, create the container.
+# sudo lxc-create -t debian -n deb386
+Next, login with root/root, change the root password, create a user, install sudo, and add the user to sudo.
+# apt-get install sudo vim-tiny
+# usermod -G sudo myuser
+From now on, I switch to logging in to the container using ssh as the user I just created. I use
+ssh-copy-id so I don't need a password to log in. Once logged in as a user, install the packages
+needed by GHC and download the [binary package](http://www.haskell.org/ghc/download_ghc_7_4_2) for
+GHC. (Readers from the future: you might consider a later version of GHC, probably the same one
+used by the latest haskell platform.)
+# sudo apt-get install wget bzip2 libgmp3c2 gcc make libgmp3-dev zlib1g-dev
+Extract ghc, configure and install. Note I install ghc in a path in opt so in the future I can
+upgrade to a new version of GHC easily.
+# ./configure --prefix=/opt/ghc.7.4.2
+# vi ~/.bashrc, add /opt/ghc.7.4.2/bin to the path
+Next, download the latest [cabal-install](http://hackage.haskell.org/package/cabal-install) source
+package (the link near the bottom for cabal-install-ver.tar.gz). I copy and paste the link to wget
+inside the terminal. Extract cabal, and run bootstrap.sh to install cabal locally for your user.
+Note, an alternative is to install the [Haskell Platform](http://www.haskell.org/platform/) from
+source, but this requires several more debian packages like opengl installed, and since we are just
+going to be using virthualenv anyway, the haskell platform isn't required.
+# cd cabal-install-0.14.0
+# vi ~/.bashrc, add ~/.cabal/bin to path
+Next, update the cabal repo and install virthaulenv. Note, virthaulenv was recently renamed as
+hsenv but hsenv has not released yet. Readers from the future should use hsenv instead once it is
+# cabal install virthualenv
+Now that cabal and virthaulenv are installed, you have a full-featured build machine for Haskell.
+Right now I build manually by cloning my repo inside the container and running the appropriate
+virthaulenv and cabal build commands, but I am considering writing a simple build script which pulls
+The main use for my container is for [gitit](http://gitit.net/) and
+[yesod](http://www.yesodweb.com/) to deploy servers to my debian stable server. But these are
+slightly more complicated so I will leave talking about them to a future post. But as a short
+example, I show how pandoc can be compiled. These are generic virthualenv commands, see the
+virthualenv README for more information.
+# mkdir pandoc && cd pandoc
+# source .virthualenv/bin/activate
+Now the binary at ~/.cabal/bin/pandoc can be copied to debian stable and run.
+The main issue with packages compiled this way is cabal's data directory, which programs access using
+Whichever directory is used to compile for example gitit must be present on the debian server. In a
+future post I will explain in more detail how to make gitit deployable. Note this issue will even
+partially hurt pandoc compiled as above, since pandoc also uses getDataFileName for some templates.