Overlay Mounting as non-root

Note: This information has only been tested on Ubuntu 16.04 and 18.04.

There are times when you want to not modify the contents of a directory directly when working within it. For example, when dealing with some projects that litter the working directory with object and temporary files.

In the past, I would have sudo mount an overlayfs (or unionfs). This would then require entering a password on mount and unmount, which was less than ideal.

With the addition of “user namespaces” (and some permissions), we can do this as a non-privileged user.

The Steps Described

To enter a namespace, use the unshare command. For the first stage, we need to create a namespace that hides mounts and provides root-like permissions.

unshare -rm

Once we’re in this namespace’d shell, we can run our mount command, whereas previously we would have to sudo mount it.

mount -t overlay overlay -o lowerdir=/path/to/lower,upperdir=/path/to/upper,workdir=/path/to/workdir /path/to/mnt

For reference,

  • lowerdir – the (read-only) directory that is the basis for the content
  • upperdir – the directory to write changes into
  • workdir – a (empty) directory that overlayfs uses as a working area

At this point, you can do all your work in the mounted directory and be sure that changes are only reflected in the upperdir once you’re done with the mount.

Note: if the mount command generates a “special device overlay does not exist” error, check if you’ve typed the options and paths correctly. The message is a complete red herring…

However, there are cases where you do not want to run commands as fake-root, so you can create another (nested) namespace to put you back as your user.

unshare -U

After you’re all done, just back out of the (now two) shells, to get you back to the original shell. The mount is automatically cleaned up, and you can access see all the changes in the upperdir – and delete them all.

Automating the Steps

While running things manually is nice and all, I do this sufficiently that scripting it all is beneficial to my sanity.

First, we need a script that gets run under the fake-root namespace:

#!/bin/bash
mount -t overlay overlay -o lowerdir="$PWD",upperdir="$PWD.upper",workdir="$PWD.workdir" "$PWD"
if [ $? -ne 0 ]; then
  exit 2
fi

cd "$PWD"
unshare -U bash --init-file <(echo "PS1='overlay|\w> '")

And then you start it all by running unshare -rm overlay.sh, which leaves you with a shell in the mounted directlry.

More Automation

Is that not enough? Of course not – I had to run the first unshare command! I don’t want to remember that…

#!/bin/bash

# create working directory
rm -rf "$PWD.workdir"
mkdir "$PWD.workdir"

# wipe out any upper directory if it's already there!
rm -rf "$PWD.upper"
mkdir "$PWD.upper"

cat << EOM > "$PWD.script"
mount -t overlay overlay -o lowerdir="$PWD",upperdir="$PWD.upper",workdir="$PWD.workdir" "$PWD"
if [ \$? -ne 0 ]; then
  exit 2
fi

cd "$PWD"
if [ -z "$@" ]; then
  unshare -U bash --init-file <(echo "PS1='overlay|\w> '")
else
  unshare -U $@
fi
EOM

function finish {
  rm -rf "$PWD.workdir"
  rm -rf "$PWD.script"
  # keep upper around in case I want to poke at it
}
trap finish EXIT

unshare -rm bash "$PWD.script"

And then you run the script from the directory you want to overlay, providing an optional set of parameters in case you want to just execute things directly.