How to mount Oracle VirtualBox shared folder using systemd unit file at system startup? How to execute a script during reboot on the shared folder from Vbox? RequiresMountsFor doesn't work with Oracle VirtualBox shared folder feature.
In this tutorial I will share the instructions required to access shared folder from Oracle VirtualBox during reboot/startup stage. You can also use this article as a reference if you are using any other third party network server such as AWS to create a share and access them during reboot or shut down stage.
Lately I got to know about this issue from one of my readers wherein he was unable to access the network share when the node was rebooting. Although if the VM is UP and running the shares are properly accessible. So I thought to give it a try as I had been getting similar questions from some other users.
Lab Environment
I am using shared folder feature from Oracle VirtualBox which allows to share a folder from Windows Host to the Virtual Machine. The interesting part is VirtualBox also has a feature of "Auto-Mount
" wherein it will mount this share on the VM automatically during reboot without any additional configuration required on the Linux client.
We will create a script which is supposed to write some data into this shared folder when the VM node is coming up after reboot. Now this script will be executed as part of systemd service which will be configured to call the script only if our shared folder is in mounted state.
Now this "Auto-Mount
" feature, sounds cool right? Well turns out it has it's own pros and cons. Let's perform our case study!
I have already written a well descriptive article to create shared folder in VirtualBox, so I will not repeat the steps here. I have a shared folder D:\shared
on my windows host which is to be mounted on /media/linux_dir
Since everything is already configured, here is a snippet of the mounted share from my Linux VM:
# df -h /media/linux_dir/
Filesystem Size Used Avail Use% Mounted on
shared 235G 117G 118G 50% /media/linux_dir
Step-2. Create dummy script (Optional)
I assume you already have your script which you plan to execute at system startup or shutdown. But for the sake of this article, let me create one (/root/create_dir.sh
). This will be a simple script which just does some pre-checks and then creates a directory with timestamp into this shared folder.
Step-3. Create systemd service unit file
Next we will create the service unit file which will execute our script during system startup. From our previous article we know that RequiresMountsFor
will check for the mount point and then start the respective service.
Additionally target units will complement all configured dependencies of type Wants=
or Requires=
with dependencies of type After=
unless DefaultDependencies=no
is set in the specified units.
# cat /etc/systemd/system/access-share.service [Unit] Description=Access VBox shared folder DefaultDependencies=no RequiresMountsFor=/media/linux_dir [Service] Type=simple RemainAfterExit=yes ExecStart=/root/create_dir.sh [Install] WantedBy=multi-user.target
Reload the systemd daemon to activate the changes
# systemctl daemon-reload
Before we do a reboot, let's just start the service and make sure if it is able to execute our script which will further create a directory under our shared folder /media/linux_dir
# systemctl start access-share
Check the status of the service
Verify if the directory was properly created:
# ls -l /media/linux_dir/
total 0
drwxrwx--- 1 root vboxsf 0 Aug 30 16:58 dir_30-08-2020_16-58-12
So runtime the service working as expected and it created the directory inside the shared folder. Next enable the service to auto-start on reboot:
# systemctl enable access-share Created symlink /etc/systemd/system/multi-user.target.wants/access-share.service → /etc/systemd/system/access-share.service.
Reboot the node and verify if there is another directory under /media/linux_dir/
# ls -l /media/linux_dir/ total 0 drwxrwx--- 1 root vboxsf 0 Aug 30 16:58 dir_30-08-2020_16-58-12
Huh, I still have single directory. What the hell happened? Luckily I have setup debug logs
Below output is from my log where I am listing the available mount units:
starting at Sun Aug 30 17:01:41 IST 2020
UNIT LOAD ACTIVE SUB JOB DESCRIPTION
-.mount loaded active mounted Root Mount
boot.mount loaded inactive dead start /boot
dev-hugepages.mount loaded active mounted Huge Pages File System
dev-mqueue.mount loaded active mounted POSIX Message Queue File System
proc-fs-nfsd.mount loaded activating mounting start NFSD configuration filesystem
proc-sys-fs-binfmt_misc.mount loaded inactive dead Arbitrary Executable File Formats File System
sys-fs-fuse-connections.mount loaded inactive dead FUSE Control File System
sys-kernel-config.mount loaded active mounted Kernel Configuration File System
sys-kernel-debug.mount loaded active mounted Kernel Debug File System
● sysroot.mount not-found inactive dead sysroot.mount
tmp.mount loaded inactive dead Temporary Directory (/tmp)
var-lib-nfs-rpc_pipefs.mount loaded inactive dead start RPC Pipe File System
LOAD = Reflects whether the unit definition was properly loaded.
ACTIVE = The high-level unit activation state, i.e. generalization of SUB.
SUB = The low-level unit activation state, values depend on unit type.
JOB = Pending job for the unit.
13 loaded units listed.
To show all installed unit files use 'systemctl list-unit-files'.
/media/linux_dir dir not available
I couldn't find media-linux_dir.mount
in the output. Let's check if this mount file is loaded now.
# systemctl list-units --all | grep linux_dir
media-linux_dir.mount loaded active mounted /media/linux_dir
YES, this mount is loaded, and I can also see the shared folder is mounted
# df -h /media/linux_dir/
Filesystem Size Used Avail Use% Mounted on
shared 235G 117G 118G 50% /media/linux_dir
- I tried different combinations of
After=
,Before=
,Requires=
,WantedBy=
and nothing worked with Oracle VirtualBox shared folder. - Then I started to realise the problem is, this shared folder is getting mounted to my VM using the "
Auto-Mount
" feature which is not controlled by systemd. - Hence systemd fails to determine if the mount file is loaded and active unlike all other mount files which are from the system.
- So to fix this I should disable
Auto-Mount
and use/etc/fstab
or systemd mount file to mount this shared folder. - Then we can add a dependency for this mount file for the access-share service so hopefully this should work
Let's test this theory
Let's disable the Auto-Mount feature of this shared folder. Open the Machine Settings → Shared Folders. Choose your shared folder and un-check the Auto-Mount option. Click on OK to save the changes.
You can also use /etc/fstab
but I have got used to systemd so I prefer this solution. Below is my sample systemd unit file to mount the shared folder. I prefer to use /etc/systemd/system
to create my custom systemd unit files.
Following is sample output from /etc/systemd/system/media-linux_dir.mount
:
[Unit] Description=VBox shared directory DefaultDependencies=no Conflicts=umount.target Before=local-fs.target umount.target After=swap.target [Mount] What=shared Where=/media/linux_dir Type=vboxsf Options=defaults,uid=root,gid=vboxsf,umask=007 [Install] WantedBy=multi-user.target
fstab
then append below entry (modify the values based on your environment) in /etc/fstab
.
# SHARED_FOLDER_NAME /MOUNT_POINT_ON_CLIENT TYPE_OF_FS OPTIONS DUMP PASS
shared /media/linux_dir vboxsf defaults,uid=root,gid=vboxsf,umask=007 0 0
Here we have to explicitly provide the UID
, GID
and umask
or else by default user and group permission will be assigned to root
user and umask 000
will be assigned. So any file or directory created will have full permission.
Since we know that the Virtual Box shared folder is owned by root
and vboxsf
, we will apply the same permission with umask 007
.
Next start this unit file to make sure, it is able to mount our shared folder (Obviously you should unmount the shared folder if already in mounted state)
# systemctl start media-linux_dir.mount
Check the status of this unit file
Step-8. Verify the systemd mount unit file
Verify if the shared folder is mounted
# df -h /media/linux_dir/
Filesystem Size Used Avail Use% Mounted on
/shared 235G 117G 118G 50% /media/linux_dir
So the unit file is working properly
Let's enable the unit file and reboot the node to make sure the same works after reboot
# systemctl enable media-linux_dir.mount Created symlink /etc/systemd/system/multi-user.target.wants/media-linux_dir.mount → /etc/systemd/system/media-linux_dir.mount.
Post reboot verify the shared folder mount point
# df -h /media/linux_dir/
Filesystem Size Used Avail Use% Mounted on
/shared 235G 117G 118G 50% /media/linux_dir
So our systemd unit file is working as expected.
Now that our systemd mount file is ready which will mount the shared path. Next we can use our existing systemd service unit file from chapter 3 of this tutorial to access the shared mount path and write some content.
I have added an additional Conflicts=
parameter to make sure when our service is executed, umount.mount
is turned off.
# cat /etc/systemd/system/access-share.service [Unit] Description=Access VBox shared folder DefaultDependencies=no Conflicts=umount.target After=media-linux_dir.mount RequiresMountsFor=/media/linux_dir [Service] Type=simple RemainAfterExit=yes ExecStart=/root/create_dir.sh [Install] WantedBy=multi-user.target
Reload the systemd daemon to activate the changes
# systemctl daemon-reload
Start the service and verify if it is working as expected.
# systemctl start access-share
Check the status of the service
We also have a new directory under /media/linux_dir
# ls -l /media/linux_dir/
total 0
drwxrwx--- 1 root vboxsf 0 Aug 30 16:58 dir_30-08-2020_16-58-12
drwxrwx--- 1 root vboxsf 0 Aug 30 20:53 dir_30-08-2020_20-53-33
Now let's reboot the node and check if we have a third directory:
# ls -l /media/linux_dir/
total 0
drwxrwx--- 1 root vboxsf 0 Aug 30 16:58 dir_30-08-2020_16-58-12
drwxrwx--- 1 root vboxsf 0 Aug 30 20:53 dir_30-08-2020_20-53-33
drwxrwx--- 1 root vboxsf 0 Aug 30 20:55 dir_30-08-2020_20-55-56
And finally we have our third directory in place so everything is working.
Conclusion
In this tutorial we learned how we can manage systemd service unit file when it has to access a network share. The best way to add a dependency for fstab mount is using RequiresMountsFor
which will make sure if the mount point is in use but this is only possible when the partition is mounted locally using /etc/fstab
. So if you are using a network share then you also have to mount the share locally.
Alternatively you can apply different hack such as add a loop in your script to check for the mount point and network share before performing the script action.
eh sorry for asking, but in step 9 you’re using a script file instead of all data you entered in step 7, do I still need the unit or should I use the service? and what’s in the script file?
Sorry for not mentioning this in the article itself, I have updated the article. The script is a dummy one which I have created in Step 2 for demonstration.
There are two unit files required for this exercise
1. To perform the auto-mount (which is normally done by fstab but instead of fstab we choose to create a systemd mount file – step 7)
2. systemd service unit file to call the actual script which needs to access the shared folder for read/write operation – step-9 (step-3 was added to show that by default it doesn’t work)