Linux Virtualization

analyze / mount virtual images (VDI) from VirtualBox

Sometimes you would like to look into a virtual image (VDI file) of VirtualBox without starting the VM. One solution could be to setup another VM and attach the VDI to the helper VM. An easier solution would be the analysis with standard Linux tools.

You can use the QEMU tools to mount your virtual disks. First you have to install these tools if not already present (here for Ubuntu):

apt install qemu-utils

Then you should create a snapshot of your virtual image, so that modifications are not written back to your image. If you need to manipulate a virtual image you can skip this step.

qemu-img create -f qcow2 -b VIRTUALDISK.vdi snapshot.qcow2

Then you will use qemu-nbd to create a block device of your virtual image. To use qemu-nbd you need to have to load the kernel module nbd.

sudo modprobe nbd
lsmod | grep -Fi nbd 

The last command should output something like:

nbd                    40960  0

Then you will connect the blockdevice /dev/nbd0 with your virtual image:

qemu-nbd -c /dev/nbd0 snapshot.qcow2

Then you can use it like every other disc. For example with fdisk or lsblk or you can mount a partition of the virtual image.

fdisk -lu /dev/nbd0
lsblk -i /dev/nbd0
mount /dev/nbd0p1 /mnt

After you finished your analysis, you have to disconnect the virtual image:

qemu-nbd -d /dev/nbd0

If you created a snapshot you can easily remove this file.


using sytem clipboard with tmux

If you are using tmux to handle your multiwindow console, you should be familiar with the copy text function (CTRL+A + [ then cursors and SPACE to select text then ENTER and insert with CTRL+Aa + ]) .

If you are also using the vim mode for navigating in copy mode you can set your Y key for yanking text into the system clipboard. So you can use ENTER for tmux internal copy and Y for copy to system clipboard.

First you should check that you have xclip installed, or you need to install it (here Ubuntu):

apt install xclip

Now you have to check your tmux version:

tmux -V

If you have tmux < 2.5, you have to add this to your tmux.conf (or enter it in live tmux session with CTRL+A + :)

bind -t vi-copy y copy-pipe 'xclip -in -selection clipboard'

If you have tmux >= 2.5, you have to add this to your tmux.conf:

bind -T copy-mode-vi y send-keys -X copy-pipe-and-cancel 'xclip -in -selection clipboard'

Of course this works by default only using a local tmux session.


configure docker network size

Docker uses by default /16 network for every network you create with it. This means you have 65534 available IPs in this network. Especially if you use docker-compose, you will create a network for every project / docker-compose file you run.

If you create to many networks, docker will use ip addresses from or from The chance this interference with your given network is then high. So you should think about the needed network size and adjust the default settings.

Because I mostly did not run many containers, but many projects and so many networks, I use a /27 network for every network. This means I have 30 available IPs. Because I typically have not more than 10 containers in one network, this is enough. You can also choose another network size depending on your needs:

Network SizeIPsavailable IPs

Now change your docker default config in /etc/docker/daemon.json. You have to create the file, if it didn’t exists. And add the setting default-address-pools:

            "scope": "local",

You can choose as base everything you want, but please use only IPs reserved for private networks.


generate HTML MimeMessage with Java

If you want to send some emails with your Java application, you may also want to format these mails using HTML. To achieve this, you have to build a correct multipart message defined in RFC 2045 and RFC 2046 and some more.

The header information of an email, like recipient, subject, etc., differs not from plain text mails:

MimeMessage mimeMessage = new MimeMessage((Session) null);
mimeMessage.addRecipient(Message.RecipientType.TO, new InternetAddress("", "Mr. Bar"));
mimeMessage.setSubject("My Subject", "UTF-8");

You should use a common character encoding for subjects. UTF-8 is a recommended and public supported one. This also applies for message content.

Now create the message body:

//create multipart
MimeMultipart content = new MimeMultipart("alternative");
//create simple textpart; content-type text/plain
MimeBodyPart textPart = new MimeBodyPart();
textPart.setText("content which is displayed, if mail client did not support HTML mails", "UTF-8");
//adds text part to multipart
//create html textpart; content-type text/html
MimeBodyPart htmlPart = new MimeBodyPart();
htmlPart.setText("<html><body><p>My Mailtext</p></body></html>, "UTF-8", "html");
//set content of mail to be multipart

inspect a systemd service

To inspect a systemd service, you need some handy commands.

Examine service names

First you have to get the correct service name you want to inspect.

systemctl list-units --type=service

You can use grep to filter the list.

Gather information of service

You can show the current status of a service with:

systemctl status servicename

Then you can display all options that describe the service:

systemctl show servicename

And you can show all files which belongs to the service description:

systemctl cat servicename

class based JSR303 – validator adding error on property

Sometimes it is necessary to validate one property or multiple properties of a class at one time or in relation to each other, but you want to add a constraint violation to the specific property. The solution will described in this post

You have your model:

public class Model {
    private int id;

    private boolean flag;

    private String field;

    ... // getter and setter following

As you see the class uses a custom validator ValidateFieldIfFlag to validate a Model instance.

So you have the annotation:

@Constraint(validatedBy = {ValidateFieldIfFlagValidator.class})
@Target({ElementType.FIELD, ElementType.PARAMETER, ElementType.TYPE})
@Retention(value = RetentionPolicy.RUNTIME)
public @interface ValidateFieldIfFlagValidator
	String message() default "my error message";

	Class<?>[] groups() default {};

	Class<? extends Payload>[] payload() default {};

And your validator:

public class ValidateFieldIfFlagValidator implements ConstraintValidator<ValidateFieldIfFlagValidator, Model>
    public boolean isValid(Model model, ConstraintValidatorContext context) {
        if (!model.isFlag()) return true;
        //if flag is set, field should be nonEmpty      
        return model.getField() != null && !model.getField().isEmpty();

The validator will validate the field to be non empty, if the flag is set. Unfortunately you will receive a ConstraintViolationException for the whole instance and not only for the field. To change this, you have to modify the validator:

public class ValidateFieldIfFlagValidator implements ConstraintValidator<ValidateFieldIfFlagValidator, Model>
    public boolean isValid(Model model, ConstraintValidatorContext context) {
        if (!model.isFlag()) return true;
        //if flag is set, field should be nonEmpty      
        if (model.getField() != null && !model.getField().isEmpty()) return true;
        ConstraintValidatorContext.ConstraintViolationBuilder constraintViolationBuilder = context.buildConstraintViolationWithTemplate(context.getDefaultConstraintMessageTemplate());
        return false;

This suppress the default, class matched ConstraintViolationException, and creates a ConstraintViolationException matching the property “field”.


disable shutdown, reboot or suspend temporarily in systemd

Sometimes you have some long running uninterruptible processes or tasks, which should not be terminated or killed under normal circumstances. For this problem systemd provides a simple solution to prevent the shutdown or reboot of a system

You just have to use systemd-inhibit for starting your process. As long as your process is running, systemd-inihibt will delay or block a shutdown or reboot task. The following operations can be inhibited:

  • shutdown
  • sleep
  • idle
  • handle-power-key
  • handle-suspend-key
  • handle-hibernate-key
  • handle-lid-switch

In default settings you would inhibit idle, sleep and shutdown.

You can view all current inhibits with:

systemd-inhibit --list

To block a shutdown while you are burning a CD, you would run:

systemd-inhibit wodim foobar.iso

You also can inhibit a specific behavior by time using the sleep command. To disable automatic sleep mode for one day, when you close the lid of your laptop, you would run:

systemd-inhibit --what=handle-lid-switch sleep 1d

Linux Networking

partial use of DNS in OpenVPN split-tunnel in Ubuntu

In Ubuntu 18.04 LTS my network configuration is setup by NetworkManager and DNS is provided by systemd. If you use a split-tunnel, which means you didn’t route all your traffic through the VPN connection, the DNS server announced by the VPN server will not be used in any situation.

To solve this issue, you can use the script update-systemd-resolved to automatically correct the DNS settings after OpenVPN connection.

As I wrote, NetworkManager didn’t support all OpenVPN options, you have to use openvpn directly and not via NetworkManager to use this solution.


First you have to save the script to your disk. I saved it in path /etc/openvpn/scripts/update-systemd-resolved.


Then you have to modify your OpenVPN profile and add the following lines to the end:

dhcp-option DOMAIN-ROUTE
script-security 2
setenv PATH /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
up /etc/openvpn/scripts/update-systemd-resolved
down /etc/openvpn/scripts/update-systemd-resolved

This will run the update script after connection setup and before tear down. Additionally it will mark all DNS queries to to use the DNS server provided by the VPN tunnel and not the already defined DNS server.

To check if it is successful, you can run:

systemd-resolve --status

And the output should contain something like:

Link 34 (tun0)
      Current Scopes: DNS
       LLMNR setting: yes
MulticastDNS setting: no
      DNSSEC setting: no
    DNSSEC supported: no
         DNS Servers:
          DNS Domain:

Link 3 (wlp4s0)
      Current Scopes: DNS
       LLMNR setting: yes
MulticastDNS setting: no
      DNSSEC setting: no
    DNSSEC supported: no
         DNS Servers:
          DNS Domain: ~.

run custom script on USB connect in Linux

You can run custom scripts after you have connected a USB device to a Linux system. So you can then perform custom actions also only if a specific device was plugged in.

In modern Linux systems the udevd daemon is used to handle the devices. You can define rules for specific actions the udev should do.

First you have to gather some informations about your target device. You can use the command udevadm monitor to monitor udev events. Some useful commands are also:

udevadm monitor -pview all events with full properties
udevadm monitor -p -s blockview all events with full properties of block subsystem related events

If your device is already connected, you can also query the attributes of an existing device using (for example disk /dev/sdb): udevadm info -a -n /dev/sdb

Here you should extract some unique attributes of your device.

To run your custom script or command you have to create such a rules file, for example /etc/udev/rules.d/10-myusbstick.rules, defining the match rules for your extracted attributes and the wanted action.

SUBSYSTEM=="block", ACTION=="add", ENV{DEVTYPE}=="partition", ATTRS{idProduct}=="441a", ATTRS{idVendor}=="0815", ATTRS{serial}=="123697755110", ENV{UDISKS_AUTO}="0", ENV{UDISKS_IGNORE}="1", RUN += "/usr/local/sbin/"

You should check that for every event the attributes are matching, the script will be started. So if your rule is too wide, you will call your script multiple times. You can use udevadm monitor to monitor the events and you also can use a simple debug script to get a feeling about the handling:

echo "got event in pid: $$" >> /tmp/udevdebug.log
env >> /tmp/udevdebug-$$.log

The script will add an entry to the file /tmp/udevdebug.log with the own PID and will output the full environment, which contains all relevant variables from udevd, to an logfile.

Linux Networking

import OpenVPN connection into Linux NetworkManager

The most desktop oriented linux distributions uses NetworkManager for configuring the network interfaces. NetworkManager also supports VPN connections and so there is also a plugin for OpenVPN. To use it, you can use NetworkManager UI and setup your VPN connection or you can import a .ovpn file, also via console.

sudo nmcli connection import type openvpn file /home/frank/myconnectionprofile.ovpn

NetworkManager will parse the ovpn file and extract all known settings and convert it to an NetworkManager VPN profile. Unfortunately NetworkManager doesn’t support every OpenVPN directive, so it may not work. If this is the case you can only use openvpn directly to connect to the VPN.

openvpn myconnectionprofile.ovpn