Help with shared read-write folder on unprivileged VM with disk device or sshfs

I’d like to have a VM for development, where I can edit code on the host system that the VM will see, but the VM can also edit the code/files in this path.

I’m using an arch VM

    lxc init images:archlinux "$name" --vm \
        -c security.secureboot=false \
        -c limits.memory=16GiB \
        -c limits.cpu=$(nproc) \
        -c boot.autostart=false

incus config device add $name mydisk disk source=~/incus-user path=/home/incus-user readonly=false this allows for read-write on host, but read-only in the VM. I think shift=true only works for containers, not VMs.

I’m trying sshfs but I’m stuck on that.

mkdir ~/incus-user
incus exec $name useradd -m incus-user
incus file mount $name/home/incus-user ~/incus-user

will say “ssfs mounting “$name” on /home/$HOME/incus-user” and “Press ctrl+c to finish”
but if I ls ~/incus-user it just hangs.

I do see incus.$name:/home/user on $HOME/incus-user type fuse.sshfs (rw,nosuid,nodev,relatime,user_id=1000,group_id=1000) with mount

The sshd service is enabled and running in the VM

On Ubuntu 22.04 with kernel 6.5.0 as a host, shift=true works for VMs. Try:

incus config device add $name mydisk disk shift=true source=/<path_on_host> path=/home/archlinux/<path_in_container>

shift=true isn’t relevant for virtual machines as those don’t have a shifted filesystem to begin with.

stgraber@castiana:~$ incus create images:ubuntu/22.04 v1 --vm
Creating v1
stgraber@castiana:~$ mkdir shared-space
stgraber@castiana:~$ incus config device add v1 shared disk source=/home/stgraber/shared-space/ path=/mnt/shared-space
Device shared added to v1
stgraber@castiana:~$ incus start v1

stgraber@castiana:~$ echo written-from-host > shared-space/foo
stgraber@castiana:~$ incus exec v1 bash
root@v1:~# echo written-from-vm > /mnt/shared-space/bar
root@v1:~# cat /mnt/shared-space/foo
stgraber@castiana:~$ cat shared-space/bar 

stgraber@castiana:~$ incus exec v1 bash
root@v1:~# echo overwritten-from-vm > /mnt/shared-space/foo 
stgraber@castiana:~$ cat shared-space/foo 

stgraber@castiana:~$ incus exec v1 bash
root@v1:~# ls -lh /mnt/shared-space/
total 2.0K
-rw-r--r-- 1 root   root   16 Jan 24 13:48 bar
-rw-r--r-- 1 201105 200512 20 Jan 24 13:48 foo
1 Like

Thanks, I didn’t know that shift=true isn’t relevant for virtual machines. I was misled by the fact that when a user on the host has UID and GID exactly the same as the user in VM, then the shared folder has read-write permission on both by default.

@digitalsignalperson you can use raw.idmap for VMs instead. Assuming your user on the host has UID and GID 1001 (check using id -u and id -g commands) and the user in VM has UID and GID 1000 (which is true for arch VM):

printf "uid 1001 1000\ngid 1001 1000" | incus config set <vm_name> raw.idmap -

or better yet:

printf "uid $(id -u) 1000\ngid $(id -g) 1000" | incus config set <vm_name> raw.idmap -
1 Like

Thanks for the steps. I would still get permission denied writing in the VM, but it worked after I explicity set the raw.idmap as noted by @qkiel

$incus create images:ubuntu/22.04 v1 --vm -c security.secureboot=false

$mkdir $shared
$incus config device add v1 shared disk source=$shared path=/mnt/shared-space
$incus start v1

$echo written-from-host > $shared/foo
$incus exec v1 bash
$echo written-from-vm > /mnt/shared-space/bar
bash: /mnt/incus-shared/bar: Permission denied

$ ls -la /mnt/shared-space
total 8
drwxr-xr-x 2 nobody nogroup   60 Jan 24 20:10 .
drwxr-xr-x 3 root   root    4096 Jan 24 20:10 ..
-rw-r--r-- 1 nobody nogroup   18 Jan 24 20:10 foo

$ stat /mnt/shared-space/
  File: /mnt/shared-space/
  Size: 80              Blocks: 0          IO Block: 4096   directory
Device: 24h/36d Inode: 413526      Links: 2
Access: (0755/drwxr-xr-x)  Uid: (65534/  nobody)   Gid: (65534/ nogroup)
Access: 2024-01-24 20:10:21.885842260 +0000
Modify: 2024-01-24 20:13:25.477521871 +0000
Change: 2024-01-24 20:13:25.477521871 +0000

$ exit

It’s an arch linux host system and my uid on the host is 1000.

$incus config get v1 raw.idmap

$incus stop v1
$printf "uid $(id -u) 1000\ngid $(id -g) 1000" | incus config set v1 raw.idmap -
$incus config get v1 raw.idmap
uid 1000 1000
gid 1000 1000
$ incus start v1
$ incus exec v1 bash
$ echo written-from-vm > /mnt/shared-space/bar
$ sudo -u ubuntu touch /mnt/shared-space/hi-from-1000
$ exit

on the host the hi-from-1000 is owned by 1000, and bar written by root in the vm is 65534/nobody. Is it unsafe to map id 0 to 0 if only this one folder is shared?

Aside, if I try to boot with secureboot on I get:

Error: Couldn't find one of the required UEFI firmware files: [{code:OVMF_CODE.4MB.fd} {} {code:OVMF_CODE.2MB.fd} {code:OVMF_CODE.fd} {code:OVMF_CODE.fd vars:qemu.nvram}]

on arch host with these OVFM files

pacman -Ql edk2-ovmf | grep x64
edk2-ovmf /usr/share/edk2/x64/
edk2-ovmf /usr/share/edk2/x64/MICROVM.4m.fd
edk2-ovmf /usr/share/edk2/x64/MICROVM.fd
edk2-ovmf /usr/share/edk2/x64/OVMF.4m.fd
edk2-ovmf /usr/share/edk2/x64/OVMF.fd
edk2-ovmf /usr/share/edk2/x64/OVMF_CODE.4m.fd
edk2-ovmf /usr/share/edk2/x64/OVMF_CODE.csm.4m.fd
edk2-ovmf /usr/share/edk2/x64/OVMF_CODE.csm.fd
edk2-ovmf /usr/share/edk2/x64/OVMF_CODE.fd
edk2-ovmf /usr/share/edk2/x64/OVMF_CODE.secboot.4m.fd
edk2-ovmf /usr/share/edk2/x64/OVMF_CODE.secboot.fd
edk2-ovmf /usr/share/edk2/x64/OVMF_VARS.4m.fd
edk2-ovmf /usr/share/edk2/x64/OVMF_VARS.fd

I sent incusd/instance/qemu: Add some ArchLinux EDK2 filenames by stgraber · Pull Request #430 · lxc/incus · GitHub to add some of those EDK2 firmwares you’ve listed.

Note that this still won’t help with security.secureboot=true as for that to work, we not only need the OVMF_CODE.secboot.4m.fd and OVMF_CODE.secboot.fd stuff, but we also need matching OVMF_VARS files that contain the standard secureboot keys.

Otherwise if we just use OVMF_CODE.secboot with the stock OVMF_VARS, the VM will boot in Secure Boot setup mode, which means no key loaded and can boot anything it wants which defeats the purpose of the option :slight_smile:

1 Like

You don’t have to log in as root, you can use default VM user ubuntu, like this: incus exec <vm_name> -- sudo --login --user ubuntu

1 Like

Makes sense. Similarly I’ve been using sudo -u user -- command