How to access VirtualBox shared folder at startup with systemd in Linux

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!

 

1. Configure Oracle VirtualBox shared folder

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

 

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. This will be a simple script which just does some pre-checks and then creates a directory with timestamp into this shared folder.

How to access VirtualBox shared folder at startup with systemd in Linux
Sample script to execute at startup after shared folder is mounted

 

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

How to access VirtualBox shared folder at startup with systemd in Linux
systemd service status for access-share

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

 

4. Verify if service is executed after share mount

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? Lucky 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

 

5. Why systemd fails to access shared folder during reboot

  • 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

 

6. Disable Auto-Mount for VBox shared folder

Let's disable the Auto-Mount feature of this shared folder. Open the Machine SettingsShared Folders. Choose your shared folder and un-check the Auto-Mount option. Click on OK to save the changes.

How to access VirtualBox shared folder at startup with systemd in Linux
Disable Auto-Mount on VirtualBox shared folder

 

7. Create systemd unit file to mount shared folder

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.

[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

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

How to access VirtualBox shared folder at startup with systemd in Linux
Mount VirtualBox shared folder using systemd unit file

 

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.

 

9. Create systemd service unit file

We can use our existing systemd service unit file from chapter 3 of this tutorial. 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

How to access VirtualBox shared folder at startup with systemd in Linux
systemd service status for access-share.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

 

10. Verify if service is executed after share mount

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.

Leave a Comment

Please use shortcodes <pre class=comments>your code</pre> for syntax highlighting when adding code.