Dedicated servers are headless machines (computers with no monitor attached) meant to run non-graphical software such as servers. Why would you need to install Windows with remote graphical access ? Well, one of the reason is continuous integration. It's an important part of the software development cycle and when you don't want a paid service, you'd have to run your runners/slaves/workers/nodes (whatever they're called these days) on a 24/7 machine. But this article isn't about continuous integration, it's about setting up, remotely and with a terminal, a virtual machine and its maintenance practices.
In this article, I'll explain how to create a VM, create a secure remote graphical access using the RDP protocol, install guest additions, take snapshots for administrative purpose and have it started at boot time. At the end, you'll even be able to start and shut it down using the following standard command.
sudo systemctl start|stop vm
Note that if during the procedure you run into "vboxdrv kernel module is not loaded" issue, you'll need to switch to the default kernel. See previous article to fix it. Also, the following was tested on ArchLinux but it should not be much different for the other distributions.
Isolating the service with a system user and a partition
I like to isolate each service running on my dedicated server. In this case, this is about creating a system user and, eventually, limiting it to a given partition. Actually I also like naming services after Pokémon, therefore I'll use the name Pikachu.
Start with creating a regular system user
pikachu with a standard home
directory if you don't care about partition. This will create
/home/pikachu and this is where we'll be installing the virtual
sudo useradd -m -s /bin/bash pikachu
But if you have the luxury to create a dedicated partition, you will
want to create the system user and set his home directory later on.
Assuming the partition is at
/mnt/pikachu, you need the following.
sudo useradd -s /bin/bash pikachu sudo chown pikachu:pikachu /mnt/pikachu sudo usermod --home /mnt/pikachu pikachu
The catch here is that the home directory must be owned by the
user. However, it must be created first.
No password was created for this system user, instead we'll use root privilege (no need to create a password that we won't remember).
sudo su - pikachu
This log us in as the
pikachu user and automatically change the
current working directory to its home directory. The rest of the
procedure is exclusively done under this user.
Creating and configuring the VM
For the next step, you obviously need VirtualBox installed. Use the underlying package manager to install it.
sudo pacman -S virtualbox
Create the virtual machine
Pikachu with the following command. Note
--ostype is important as it configures the machine with
settings known to work for the given operating system.
vboxmanage createvm --name "Pikachu" --ostype Windows10_64 --register --basefolder pikachu
Now that we have given the virtual machine a name, we have to use it in every subsequent commands. If the virtual machine was successfully created, a message like that should appear.
Virtual machine 'Pikachu' is created and registered. UUID: e9eacc2a-162a-4eb1-bfbd-6d49df306a60 Settings file: '/mnt/pikachu/.config/VirtualBox/pikachu/Pikachu/Pikachu.vbox'
After that you should configure the virtual machine with the CPU count, the RAM and VRAM size. You'll want change the values according to how you want to share the resource of your dedicated server across the different services.
vboxmanage modifyvm "Pikachu" --cpus 2 vboxmanage modifyvm "Pikachu" --memory 2048 vboxmanage modifyvm "Pikachu" --vram 128
We'll need to create a virtual hard disk and attach the Windows ISO file to the virtual "CD reader". Use the following set of self-explanatory command-lines to do that job. Adjust the size of the hard disk (expressed in Mb) and the path to the ISO file if necessary.
vboxmanage createhd --filename pikachu.vdi --size 100000 vboxmanage storagectl "Pikachu" --name "IDE Controller" --add ide vboxmanage storageattach "Pikachu" --storagectl "IDE Controller" --port 0 --device 0 --type hdd --medium pikachu.vdi vboxmanage storageattach "Pikachu" --storagectl "IDE Controller" --port 1 --device 0 --type dvddrive --medium Win10_1709_EnglishInternational_x64.iso
We're pretty much set up to start the virtual machine but we need one more thing... a remote graphical access to it.
Securing a remote graphical access
Unfortunately, we'll still have to install Windows the old fashion way and for that... we need a graphical access. We're using the RDP protocol so a client like Remmina on Linux does the trick.
First off, let's open the port for the connection. If you have a firewall set up like UFW, you'll want to type this.
sudo ufw allow 5012
We can configure the virtual machine to start a graphical server on port 5012 with the following.
vboxmanage setproperty vrdeauthlibrary "VBoxAuthSimple" vboxmanage modifyvm "Pikachu" --vrde on vboxmanage modifyvm "Pikachu" --vrdeport 5012 vboxmanage modifyvm "Pikachu" --vrdeauthtype external
This has set up the machine to use the username/password authentication
mechanism, therefore, few more lines are needed to finish the
configuration. I usually generate passwords with the
pwgen -s command.
For this article, I'll use
vboxmanage internalcommands passwordhash "Sf5gi5nO" vboxmanage setextradata "Pikachu" "VBoxAuthSimple/users/sonkun" 15c889ee10763046eb56756da971e606b162bed7f3d5edfd7eaf868b47eb0fad
The first line generate the hash version of the password. Collect the
output and reuse it in the second command which will actually set up the
machine instance. Note that the occurrence
sonkun refer to the
username, change it accordingly.
Having the VM start at boot time
To start the virtual machine we'd actually have to type
vboxmanage startvm "Pikachu" --type headless but it'd more convenient
to just use the standard service manager systemd. Plus we also need to
start it at boot time.
We do it by creating a system service configuration file in
/etc/systemd/system that we name
pikachu.service, then put the
following content in it.
[Unit] Description=Pikachu VM After=network.target [Service] User=pikachu Type=forking ExecStart=/usr/bin/vboxmanage startvm "Pikachu" --type headless ExecStop=/usr/bin/vboxmanage controlvm "Pikachu" poweroff [Install] WantedBy=multi-user.target
After it's done, two more commands are needed. The first one is to make systemd aware of our new script, and the second is to start the service at boot time.
sudo systemctl daemon-reload sudo systemctl enable pikachu
Now you can start the virtual machine with
sudo systemctl start pikachu
and shut it down with
sudo systemctl stop pikachu. From now on, you
should be fine on your own but let me assist you during the installation
of Windows to teach you a couple of awesome tricks.
Initial installation of Windows
I'll go through the Windows installation step with you to talk about snapshots which come in extreme handiness when it comes to administrating and updating a VM.
At this point, you should have started the VM and installed Windows on it. Now there are couple more things to do. First is removing the initial Windows ISO file, and putting the guests addition ISO file in the VM's CD reader.
While the guests additions ISO file can be downloaded from the official website of VirtualBox, on ArchLinux, there's a package that does just that.
sudo pacman -S virtualbox-guest-iso
The guest additions ISO file is then located here:
Shut down the VM, either directly on Windows using the Power off
button or from the command-line
sudo systemctl stop pikachu, then
proceed with removing the initial Windows ISO file and replace it with
the guest additions ISO file.
vboxmanage storageattach "Pikachu" --storagectl "IDE Controller" --port 1 --device 0 --type dvddrive --medium /usr/lib/virtualbox/additions/VBoxGuestAdditions.iso
Start the VM again, and do install the guest additions as it now appears in the File Explorer, then proceed with shutting down the VM again and this time, definitely remove any medium from the CD reader.
vboxmanage storageattach "Pikachu" --storagectl "IDE Controller" --port 1 --device 0 --type dvddrive --medium none
This has probably been a tiring step and you probably don't want to do it (ever) again. I didn't even mention that one needs to update the Windows system and using an old ISO might result in waiting a couple of hours until Windows is fully up-to-date. At this point, a snapshot can be taken. Preferably, shut down, properly" the VM before running that command.
vboxmanage snapshot "Pikachu" take windows-installed
This will save the current states of the machine and later, if anything goes wrong on it, you can just go back to where it was... the time after all the tedious things we just did. In this case, I named the snapshot "windows-installed" and it can be restored with the following command.
vboxmanage snapshot "Pikachu" restore windows-installed
In fact, you can have different variations of your Windows machine using snapshots and easily switch from one to another. Let's say you need different version of Microsoft compilers for your software, you can install one version of Visual Studio in one snapshot named "visual-studio" and MinGW in another one called "mingw". Check out the snapshot documentation for more information but this should save you hours of maintenance when done intelligently.
This was a follow-up of the previous article about fixing a common problem that occurs when running VirtualBox on dedicated servers (https://www.sonkun-dev.net/article/fix-vboxdrv-kernel-module-is-not-loaded). Now we took it to the next step and actually created and configured a VM machine quite neatly.
Hope it helped some people out there, and drop a message in the comments section below if you have a question. For the next article I might talk about installing Teeworlds servers.