9

I have my home directory at /z/home/$USER, instead of at /home/$USER, so I can have it on ZFS.

This upsets Snap packages to no end. When I try and run them, they say:

Sorry, home directories outside of /home are not currently supported. See https://forum.snapcraft.io/t/11209 for details.

When I go to that URL, I get a workaround, but not one described in sufficient detail to actually implement:

Snapd does currently not support running snaps if the home directory of the user is outside of /home. This is discussed here here.

A workaround is to bind mount the home directory outside /home into /home.

The linked thread degenerates into discussion of what the design for properly supporting arbitrary home directories ought to be, and it is not immediately apparent to me how to implement the described workaround. I tried bind mounting /z/home/$USER to also appear at /home/$USER, and telling the Snap that that is my home directory, but my Snap package I want to run is still insisting that my home directory is bad and refusing to run:

$ sudo mkdir /home/$USER
$ sudo chown ${USER}:${USER} /home/$USER
$ sudo mount --bind /z/home/$USER /home/$USER
$ HOME=/home/$USER any-snap-package 
Sorry, home directories outside of /home are not currently supported. 
See https://forum.snapcraft.io/t/11209 for details.

How, exactly, does one go about implementing the workaround described by Michael Vogt in the linked Snapcraft forum thread? Or does the workaround not actually work?

3
  • Snaps can only access a limited set of directories for security reasons (they run in restricted container like environments). It's further complicated by which confinement policy they exist in ('strict', 'classic' or 'devmode' snapcraft.io/docs/snap-confinement) Are you talking about a 'classic' confined snap? or 'strict'? (I'm suspicious a strict confinement won't allow what you want to do, but alas I'm unsure).
    – guiverc
    Feb 2, 2020 at 6:10
  • The snap in question is minetest; it is whatever confinement the default is when installing from the software center (I believe strict).
    – interfect
    Feb 3, 2020 at 0:04
  • I've had moderate success with the steps in this post: forum.snapcraft.io/t/…
    – Xetnus
    Feb 19, 2021 at 17:09

1 Answer 1

1

It seems that snap gets its information on where your home directory is straight from /etc/passwd and not from any other source. One workaround that I've been able to get mostly working involves using a Docker container to replace /etc/passwd from snap's point of view, with one that says my home directory is /home/$USER.

I'm sure there's a lighter-weight way to do this (maybe just a chroot?) that would negate the need for some of the other workarounds I needed to get snap to work inside a container, and I haven't tried it with minetest, but here's the script I put together that runs the teatime Snap without me having to actually move my home directory. Basically it starts a container with snapd in it, with all the places that snapd keeps state mounted in from outside, but initialized with the base state of a freshly installed snapd (which is what it needs the local-persist Docker volume driver for). Then it runs snap in the container, as you, with all the X11 and DBUS plumbing wired up so that teatime can show its windows and desktop notifications.

#!/usr/bin/env bash

# teatime.sh: Run the teatime snap in a Docker container
# Requires local-persist driver installed in Docker: https://github.com/MatchbookLab/local-persist
# Installs it if not available.

set -ex

IMAGE_NAME="snapdock"
CONTAINER_NAME="snaphost"
STORAGE_ROOT="/var/lib/snapdock"
PASSWD_FILE="$HOME/etc/passwd.docker"

if [[ ! -f "${PASSWD_FILE}" ]] ; then
    # The /etc/passwd that claims we have a normal home directory doesn't exist.
    # We need to make it.
    mkdir -p "$(dirname "${PASSWD_FILE}")"

    cat "/etc/passwd" | sed "s_${HOME}_/home/${USER}_g" > "${PASSWD_FILE}"
fi


if ! (docker images "${IMAGE_NAME}" | grep "${IMAGE_NAME}" >/dev/null) ; then
    # There's no image ready. We need to make one
    WORKDIR="$(mktemp -d)"
    cd "${WORKDIR}"
    cat >Dockerfile <<EOF
FROM ubuntu:18.04
# Based on https://github.com/ogra1/snapd-docker/blob/master/build.sh
ENV container docker
ENV PATH "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/bin"
ENV LANG C.UTF-8
ENV LC_ALL C.UTF-8
RUN DEBIAN_FRONTEND=noninteractive apt-get -q -y update && \
    DEBIAN_FRONTEND=noninteractive apt-get -q -y upgrade && \
    DEBIAN_FRONTEND=noninteractive apt-get -q -y install \
        fuse \
        snapd \
        snap-confine \
        squashfuse \
        sudo && \
    apt-get clean && \
    dpkg-divert --local --rename --add /sbin/udevadm && \
    ln -s /bin/true /sbin/udevadm
VOLUME ["/sys/fs/cgroup"]
STOPSIGNAL SIGRTMIN+3
CMD ["/sbin/init"]
EOF
    docker build . -t "${IMAGE_NAME}"
    cd -
    rm -Rf "${WORKDIR}"
fi

if ! which docker-volume-local-persist >/dev/null ; then
    # We need the local-persist driver installed into Docker.

    WORKDIR="$(mktemp -d)"
    cd "${WORKDIR}"
    curl -fsSL "https://raw.githubusercontent.com/MatchbookLab/local-persist/45c5c344d5dfd358c28d7148be48302d20456fac/scripts/install.sh" >install.sh
    chmod +x install.sh
    cat install.sh
    sudo install.sh
    cd -
    rm -Rf "${WORKDIR}"
fi

if ! (docker ps --filter "name=${CONTAINER_NAME}" | grep "${CONTAINER_NAME}" >/dev/null) ; then
    # Container is not running. Start it.

    if [[ ! -e "${STORAGE_ROOT}" ]] ; then
        # Make sure we have the directories to mount          
        mkdir -p "${STORAGE_ROOT}/lib"
        mkdir -p "${STORAGE_ROOT}/cache"
        mkdir -p "${STORAGE_ROOT}/systemd"
        mkdir -p "${STORAGE_ROOT}/snap"
        sudo chown -R root:root "${STORAGE_ROOT}"
    fi

    # Start the container
    docker run --rm --network=host --cap-add SYS_ADMIN --security-opt apparmor:unconfined --security-opt seccomp:unconfined --volume="$(echo ~:/home/${USER})"  --volume="${PASSWD_FILE}:/etc/passwd:ro" --volume="/etc/group:/etc/group:ro" --volume="/etc/shadow:/etc/shadow:ro" --volume="/etc/sudoers.d:/etc/sudoers.d:ro" --volume="/tmp/.X11-unix:/tmp/.X11-unix:rw" --volume="/sys/fs/cgroup:/sys/fs/cgroup:ro" --volume="/lib/modules:/lib/modules:ro" --device=/dev/fuse --tmpfs /run --tmpfs /run/lock --volume="/run/user/$(id -u):/run/user/$(id -u):rw" --tmpfs /tmp --volume="${STORAGE_ROOT}/lib/:/var/lib/snapd:rw" --volume="${STORAGE_ROOT}/cache/:/var/cache/snapd:rw" --mount "type=volume,volume-driver=local-persist,src=installed-snaps-systemd,target=/etc/systemd/system,volume-opt=mountpoint=${STORAGE_ROOT}/systemd" --mount "type=volume,volume-driver=local-persist,src=installed-snaps-snap,target=/snap,volume-opt=mountpoint=${STORAGE_ROOT}/snap" -it --name="${CONTAINER_NAME}" -d "${IMAGE_NAME}" >/dev/null

    # Wait for it to come up
    sleep 5

fi

# Make sure the snap is installed
docker exec snaphost snap install teatime
# Try and fail to run it as root to avoid complaints about not being able to capture mountpoints when we run it as us.
docker exec snaphost teatime || true
# Run it as us with X11 and Dbus set up
docker exec -d --user="$(id -u ${USER})" --env="DISPLAY" --env="DBUS_SESSION_BUS_ADDRESS" snaphost teatime

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.