Start Stop VirtualBox with systemd

This post will show how to start stop Virtualbox with systemd. The documentation for both auto-starting virtualbox and that for systemd I found to be appalling. The virtual box documentation has an example but that is wrong. The example code is bash and it is sourced by another file. There is a variable assignment at the top but it has spaces around the equals so it fails with a schoolboy syntax error. For systemd what there is, and there is a lot of it, does not make sense. The man pages have lots of English words that go together to mean nothing but the usual marketing bullshit we are constantly get bombarded with.

How I Got Here

I sorted out this little project I used mainly trial and error. After I found the official documentation to be a let down I read a number of answers to questions and a few blog post. None gave a complete system set up to Start Stop VirtualBox with systemd. All in all I’m very glad I had a minimal server that boots very quickly 🙂 It gets tedious waiting for the VM to boot and close down. See this post on how to create a minimal server install.

Get rid of vboxautostart-service

So to begin. The Oracle vboxautostart-service installed with Virtualbox has never worked reliably for me even after extensive hacking of the source code in the scripts. With that said we can disable that service as we will not be using it.

sudo systemctl disable vboxautostart-service

If you want a deep clean also get rid of the source unit file for vboxautostart-service. That way it can never get turned back on again. Although it will probably get put back at the next update. 🙁

sudo rm -rf /lib/systemd/system/vboxautostart-service.service

If the config directory used by vboxautostart-service was created you can also delete that too. We will not be using anything in there either.

sudo rm -rf /etc/vbox

User permissions for Virtualbox

The user who will run our VMs will need to be in the group vboxusers. If you have already been using Virtualbox then your users probable is already. First, let’s see if it is already there then append it as necessary.

groups
richard adm cdrom sudo audio dip video plugdev lpadmin sambashare

Richard is not a member of vboxusers it is not listed. Append the group to your list of existing groups, do not forget the -a for append 🙂

sudo usermod -a -G vboxusers richard

Now you will need to log out and back in again, to pick up the new group. The output of groups will show it added.

richard adm cdrom sudo audio dip video plugdev lpadmin sambashare vboxusers

New Unit File for systemd

To start stop VirtualBox with systemd we will create our own new unit file. This is a first try, we will make it better later on. This is the one and only file to create nothing else is needed. Open up the file with your favorite editor.

Create a new Unit file

sudo nano /etc/systemd/system/vm_autostart_name.service

Add this text as the contents. I picked bits from assorted posts and help documentation to get this layout. This is the bare bones that I got to work. I would love to explain what each line does, but the documentation is so bad I still do not know. 🙁

You will need to change the three occurrences of vm_name to the name of your own VM guest. Do not use a ‘-‘ hyphon or dash in the name of your VM, systemd will not allow that to work, more systemd BS. Also note the User=richard in the [Service] section I’m guessing you will need to change that too.

[Unit]
Description=VM vm_name
After=network.target vboxdrv.service
Before=runlevel2.target shutdown.target

[Service]
User=richard
Group=vboxusers
Type=forking
Restart=no
TimeoutSec=5min
IgnoreSIGPIPE=no
KillMode=process
GuessMainPID=no
RemainAfterExit=yes

ExecStart=/usr/bin/VBoxManage startvm vm_name --type headless
ExecStop=/usr/bin/VBoxManage controlvm vm_name acpipowerbutton

[Install]
WantedBy=multi-user.target

Reload systemd daemon

As you have added or changed a file that systemd uses you have to reload the daemon. If you do not reload, you get a warning from systemd to do just that and nothing will work correctly until you do. Why is systemd better than what we had already? Systemd knows the files need to be reloaded so why not do it or have an option to allow that to happen. How very Microsoft.

sudo systemctl daemon-reload

Using the service

Now we can enable our service and start to test it out.

sudo systemctl enable vm_autostart_name

We can now stop, start and use status to see how things are going. The status gives you some idea what is going on. Running tail -f on the syslog gives a little bit more info when you start to debug your service for typos.

sudo systemctl start vm_autostart_name
sudo systemctl stop vm_autostart_name
sudo systemctl status vm_autostart_name

That should all be working now. From the command line try starting it up and the seeing the status. Stop the VM and make sure that workings. You should also be able to shut down the host and the VM will shutdown and then restart as the host is booted. Almost sorted. This service only works for that one hard coded VM. That could be pain if you have many VMs.

Wildcard Names For Services

We do not want to have to create a new unit file for every VM. Yay a good popint for systemd but i could do more with a SysV init script. :). We can use a feature of systemd. I found this little gem by looking at the source of other services already installed.

Disable the vm_autostart_name.service and then rename the unit file to vm_autostart@.service. Find all occurrences of vm_name or whatever you called your VM, replacing them with %I (percent, capital I, as in ‘I’ wrote this post).

sudo systemctl disable vm_autostart_name
sudo mv /etc/systemd/system/vm_autostart_name.service /etc/systemd/system/vm_autostart@.service

Save the changes and do not forget to reload the systemd daemon it won’t do that for itself.

sudo systemctl daemon-reload

NOTE: VM names MUST be not include ‘-‘, hyphons, change them to ‘_’, underscores. Systemd annoyingly converts ‘-‘ into a ‘/’. A VM name of test-server becomes test/server and therefore cannot be found. I saw a message in the syslog when looking to see why it had failed to work.

Enable the new service

We enable this multi-use service with the name of the VM after the ‘@’ as shown below. We cannot enable the actual service name, vm_autostart@.service,from the unit file. Again in the examples below change vm_name to the name of your VM.

sudo systemctl enable vm_autostart@vm_name

And then use it with the following,

sudo systemctl status vm_autostart@vm_name
sudo systemctl start vm_autostart@vm_name
sudo systemctl stop vm_autostart@vm_name

Now we only have to enable the service for each VM, you will not have to create a new unit file etc. for each. That is, it we can now start stop VirtualBox with systemd and it will automatically start them up at boot time and close them down when the host machine is shut down.

Known problem

While testing out start stop VirtualBox with systemd I found that under some circumstances the service would not close down the VMs. If you start a VM with the service. You can then close it with the service. If you start the VM without using the service it will not close down with the service stop command. Also, if you start the VM with the service and then try to start the VM again, by mistake, you cannot use the service to close it down.

If you do find a solution please let me know.

Some not particularly helpful documents

https://www.virtualbox.org/manual/ch08.html#vboxmanage-autostart
man systemd.service
loads of other man systemd* files.

You have noticed this was a bit of a rant. Before starting this project and this post I had no particular position on systemd. Now I know it is bad. Even the developers don’t have a clue how it works, so they resort to the verbose bullshit in their man pages, to cover it up.

15 thoughts on “Start Stop VirtualBox with systemd

  1. RedCybernetic

    Thank you so much for this post. That was the solution to my VirtualBox 6.0 installation on Ubuntu Server 18.04.1. Absolute perfection!

    Reply
    1. richard Post author

      Hi, I do not see that happening. I have three virtuals running on one host. As long as you only use the systemctl commands to stop and start them then all is well. I you forget and reboot, shutdown a virtual from a terminal logging into a virtual machine then the systemctl calls will stop working. It’s all very vague and wobbly.

      I am thinking of abandoning systemctl altogether for virtualbox and just writing my own startup/shutdown scripts using calls to vboxmanage.

      Reply
  2. starbuck

    Thank you for sharing, it is exactly what I was looking for and it is working perfectly.
    Saved me a lot of time and frustration.

    Reply
  3. Bubba

    I couldn’t remember how I got this working before on 16.04 and I lost that disk anyway. This works perfectly and has saved me a lot of time. I can’t thank you enough. And I have to agree with your overall assessment of systemd.

    Reply
  4. Sam

    Hi Richard,
    the unit file you provided above did not work for shutdown on my Debian 9 (Stretch) host.
    I use Debian 9 (Stretch) and FreeBSD 12.0 guests.

    After a lot of further research I found that “KillMode=process” should be replaced by
    #KillMode=process
    KillMode=none
    TimeoutStopSec=40

    Otherwise systemd does not wait until the ExecStop command has finished and kills the virtual machine
    immediately without shutting down the guest system.

    After changing it works fine for me.

    Reply
  5. Charles A. Halsall

    Been trying for ages to get the systemd scripts to work as well as the vboxcontrol script worked under Centos 6. Thanks very much for posting this solution.

    Reply
  6. Arius

    This is a great post on how to set up the service.
    The only problem I had is that I didn’t know that text format (case) had to exactly match the VM Virtualbox name in the ExecStart and ExecStop commands.
    Again, many thanks.

    Reply
  7. Ed

    On Ubuntu 20.04 the service would always fail to start automatically. However, it would start if I started the service manually. Adding a delay in the .service file corrected the issue.

    ExecStartPre=/bin/sleep 30

    Reply
  8. Roland

    Works perfect, thanks!

    BTW: I always have to do a ‘modprobe vboxnetflt’ after a kernel update, otherwise /dev/vboxdrv does not show up.

    Reply
  9. Tony

    Thank you, Richard! An explanation this detailed on this subject is rare. I not only share in your rant, but can write a book on it!

    Reply

Leave a Reply

Your email address will not be published. Required fields are marked *