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.