Kristian Lyngstøl's Blog

A sandboxed /home directory

Posted on 2010-03-19

A while back I hacked together some aufs-based scripts for sandboxing. There are two different scenarios at hand:

  1. Sandboxing my /home-directory, so changes to applications don't get saved and my home directory doesn't fill up with lard (well, if it does, it's gone after a reboot).
  2. Making sure my firewall doesn't write to "disk" as that's a flash-card. And in the process ending up with a sandbox for /.

The two setups are very distinct, and the /home-directory is definitely easier to deal with, since things like dist-upgrades is a non-issue. People have asked me to write about it, so here it is.

The little home directory that could

The rationale behind this was: 1. Play around. 2. Keep a clean home directory.

The first thing I had to do was figure out a way to handle persistent storage and a base system. This was reasonably simple. I moved ~/Documents ~/Source and ~/tmp to my raid: /media/snop/kristian/home-base/, and made two new directories: /media/snop/kristian/home-base/sandbox and /media/snop/kristian/home-base/base. base/ was going to be ... the actual base system. So I copied my entire home directory into base/, created a git repo from it, and started deleting whatever I didn't need or want. This would include things like browser cache.

Next, I set up a tmpfs on home-base/sandbox/. Now the real magic: I stack-mounted home-base/sandbox/ on top of home-base/base/ with /home/kristian as the mountpoint. In other words: Upon initial login, /home/kristian would contain just what home-base/base/ contained, but any further changes to /home/kristian/ would now be stored in home-base/sandbox/ - a tmpfs. So how do I update it? Well, I have a git-repo in my home-directory now - since home-base/base/ was a git-repo. So I can simply make a patch and apply it to the base system - if I really want to. I've been running this for several months now, and I must say it works rather well.

I still had to handle persistence, though. But this was easy: After I mount everything, I sym-link ~/Documents, ~/Source and ~/tmp to their respective original directories now stored on /media/snop/kristian/home-base/. Just for the record: ~/Documents is a git repo itself, ~/tmp is for anything I need for a while but isn't important enough to store in a "proper" location, and ~/Source is essentially a handful of git-repos I work on.

So how was all this possible?

Simple: AUFS.


#!/bin/sh -e

set -x
LINKS="Documents Source tmp"

mount tmpfs -t tmpfs -o mode=700,size=$TMPSIZE,uid=$MYUID,gid=$MYGID $BASE/sandbox
mount -t aufs aufs $MYHOME -o relatime,dirs=$BASE/sandbox=rw:$BASE/base=ro

for a in $LINKS; do
if [ -f $MYHOME/$a ]; then
echo "Warning: $a defined as link, but present in base files."
ln -s $BASE/$a $MYHOME/$a

And this is how it looks from df, while running:

kristian@nihilus:~$ df -h /media/snop/kristian/home-base/{sandbox,base} /home/kristian/
Filesystem            Size  Used Avail Use% Mounted on
tmpfs                 500M  456M   45M  92% /media/snop/kristian/home-base/sandbox
2.8T  2.2T  527G  82% /media/snop
aufs                  500M  456M   45M  92% /home/kristian
kristian@nihilus:~$ uptime
14:37:35 up 55 days, 19:54,  3 users,  load average: 0.19, 0.27, 0.16
kristian@nihilus:~$ ls
Documents  Downloads  f  Source  tmp  ukurock.mp3

I included the uptime to point out that it took 55 days to use up the 500M (it went full yesterday). The ls-output demonstrates one of the reasons I like this setup: it's really really clean. (also: Hi Petter ;) ). I'm planning to upgrade my system so I can increase the tmpfs-size. Right now, the browser cache tends to use up most of it. But I can tell you this: Building stuff on a tmpfs is .... fun.

So far I've only had ONE misshap with data loss, which involved moving things around rather creatively. So keep that in mind if you want to try this out.

But yeah, if you're into experimenting, this is something you may want to check out. It's simple, clean and safe, given reasonable precautions. It helps that ~/Documents is already a git repo which is reasonably clean. All in all, this has been an enjoyable experience. Next step: Hooking it into pam_mount and setting it up on my laptop:

kristian@kjeks:~$ ls -a1 | wc -l

It's friday!