Arbitrary Ownership of Files on Owner-Restricted Filesystems
August 24, 2025
linux
A rising moon in October
Some programs get very upset when their files can’t be chown’d to their own special user. How can you reconcile this when you want the program to write to a location where only one user can own files?
The Problem
I recently wanted to try out Obsidian LiveSync on my “homelab” (read: mini PC which connects to a NAS SMB mount). I ran into a problem though: CouchDB, which LiveSync uses, requires that files written to the disk be owned by a user called couchdb! With my setup, only brendan can own files on Brendan’s SMB share. I needed a solution.
Enter QCOW2 files! Instead of hosting CouchDB’s files in a folder on my NAS, I can just make a virtual filesystem inside a file on the NAS! Then I can mount the filesystem and read/write with whichever user I please.
Create and Test the QCOW2 File
- Install qemu.
- Make your QCOW2 file on the NAS via
$ qemu-img create -f qcow2 /mnt/nas/my_drive.qcow2 100G. You’ve got to specify a max size, but don’t worry too much. After formatting, my max-100G file only takes up 15MB. - Mount the QCOW2 file.
- Enable the Linux NBD (Network Block Device) module:
# modprobe nbd max_part=8- You can change the max number of partitions if you like. On my Arch system,
modinforeports that the default is 16.
- You can change the max number of partitions if you like. On my Arch system,
- Connect to the QCOW2 file as a block device:
# qemu-nbd --connect=/dev/nbd0 /mnt/nas/my_drive.qcow2
- Enable the Linux NBD (Network Block Device) module:
- Partition your file:
# echo 'type=83' | sfdisk /dev/nbd0- You can also use
fdiskor your favorite partitioning software. - Type 83 is the generic Linux partition type. Feel free to change. See
echo "l" | fdisk <some disk>
- You can also use
- Make the filesystem. I chose
ext4here.# mkfs.ext4 /dev/nbd0p1 - Mount your filesystem.
# mount /dev/nbd0p1 /mnt/nas-qcow2-file - Verify that you can write as an arbitrary user to your filesystem:
echo 'test' > /mnt/nas-qcow2-file/test-9999.txt && chown 9999:9999 /mnt/nas-qcow2-file/test-9999.txt && ls -l /mnt/nas-qcow2-file/test-9999.txt- You’re looking for output similar to
-rw-r--r-- 1 9999 9999 5 Aug 24 17:25 /mnt/nas-qcow2-file/test-9999.txt. Note that the owner is 9999.
- You’re looking for output similar to
Automatically Mount the File
-
Make your mount point:
# mkdir /mnt/nas-qcow2-file- If you want your mount point to only be writable if the qcow file is mounted, use
chattr:# chattr +i /mnt/nas-qcow2-file. I recommend this.
- If you want your mount point to only be writable if the qcow file is mounted, use
-
Make a script to execute the above steps. I stored mine in
/usr/bin/mount-qcow2:1#!/bin/sh 2 3# Abort if any command fails 4set -e 5 6# The QCOW2 file to mount 7readonly QCOW_TO_MOUNT="/mnt/nas/my_drive.qcow2" 8 9# Optional: if you can guarantee /mnt/nas/my_drive.qcow2 is available, remove this block. 10# Wait until the qcow file is available 11while [ ! -e "$QCOW_TO_MOUNT" ]; do 12 echo "Could not find qcow2 file at '$QCOW_TO_MOUNT'. Waiting 10 seconds..." 13 sleep 10 14done 15 16# For some reason, this script could not find modprobe when run by cron. 17# modprobe worked just fine when running otherwise. As a band-aid fix, 18# specify the full path. 19/usr/sbin/modprobe nbd max_part=8 20 21qemu-nbd --connect=/dev/nbd0 "$QCOW_TO_MOUNT" 22mount /dev/nbd0p1 /mnt/nas-qcow2-file -
Test your script:
# /usr/bin/mount-qcow2- Disconnecting from the file might be useful here for testing:
# umount /mnt/nas-qcow2-file && qemu-nbd --disconnect /dev/nbd0
- Disconnecting from the file might be useful here for testing:
-
Set your script to run at startup. I did this via cron:
# echo "@reboot root /usr/bin/mount-qcow2 > /var/log/mount-qcow2 2>&1" > /etc/cron.d/mount-qcow2- Note that I had an issue when running this script via cron:
modprobecould not be found! I’m sure some Unix guru knows exactly why, but my band-aid fix was to specify the absolute path of the executable at/usr/sbin/modprobe.
- Note that I had an issue when running this script via cron:
-
Reboot and verify you can write to your mounted file!
Sources: