Running QEMU VM with the latest kernel inside 2.6 OpenVZ container.

There are many of cheap NAT OpenVZ VPSes on market. However, OpenVZ virtualization has certain limitations and comes with old 2.6 kernel. Hosting provider can decide to disable tun/tap, nfs or another core feautures, which makes VPS very limited in usage.

At this article we will break the rules and run latest Alpine Linux inside Debian OpenVZ 2.6.32-042stab134.8 container with 256mb RAM. Alpine is a lightweight system, which is good for slow machines.

Download any VNC viewer. We will need it for initial setup. I use standalone version of RealVNC on Windows.
UPD. You can use -curses QEMU option instead of VNC.

Download the latest Alpine ISO optimized for virtual machines.


Install QEMU.

apt install qemu

Create QEMU disk image.

qemu-img create -f raw alpine.img 2G

NAT VPSes always comes with only few open ports. Let’s calculate VNC port by the following formula:

"Desired port" - 5900.

In my case:

51221 - 5900 = 45321

Run QEMU virtual machine.

qemu-system-x86_64 \
-netdev user,id=n1 -device virtio-net-pci,netdev=n1 \
-drive file=alpine.img,cache=none,if=virtio,format=raw \
-vnc \
-m 200 \
-cdrom alpine-virt-3.9.3-x86_64.iso

This command will run VM with userspace TCP/IP stack – SLIRP, which is very handy for VPS without tun/tap support. 200 mb will be enough to start Alpine.

Next, run VNC viewer on port 51221 and login as root without password.

Before installing Alpine, we need to setup resolv.conf, so VM can use google DNS instead of one provided by QEMU DHCP server. We can not use QEMU “-netdev dns=addr” option – for some reason it’s not working.
Alpine comes with vi editor out of the box. Practice with it a little bit if you don’t know what is it.

Create resolv.conf file containing google DNS record.


Alpine comes with udhcpc DHCP client, which will overwrite resolv.conf with QEMU DNS by default. Let’s disable this feature.
Create udhcpc config dir.

mkdir /etc/udhcpc

Create udhcpc.conf with only one line.


Install Alpine.


Keyboard Layout -> none #if no need
Hostname -> qemu-test #as you want
Interface to initialize -> eth0
Ip address -> DHCP
Manual network configuration -> no
Set new root password
Timezone -> UTC #as you want
Proxy URL -> none
Mirror number -> r #random or as you want
SSH Server -> dropbear #for some reason openssh will slow down OS booting for a few minutes
Disk to use -> vda
How to use -> sys
Erase disk -> y

Shut down Alpine.


Run Alpine again, but disable VNC and enable ssh port redirect.

qemu-system-x86_64 \
-netdev user,id=n1 -device virtio-net-pci,netdev=n1 -redir tcp:51222::22 \
-drive file=alpine.img,cache=none,if=virtio,format=raw \
-nographic \
-m 200

That’s all. Virtual machine is ready to use and accept ssh connections by external IP and 51222 port.

Known limitations.

ICMP traffic is not working over SLIRP. Workaround is here (Enabling ping in the guest, on Linux hosts).
Or use virtual tap device if possible.


Cheap VPSes are comes with CPU limitations often. To limit CPU usage I use cpulimit.

git clone
cd cpulimit
cp src/cpulimit /usr/bin

Run QEMU with 50% CPU limit.

cpulimit -l 50 \
qemu-system-x86_64 \
-netdev user,id=n1 -device virtio-net-pci,netdev=n1 -redir tcp:51222::22 \
-drive file=alpine.img,cache=none,if=virtio,format=raw \
-nographic \
-m 200

1 thought on “Running QEMU VM with the latest kernel inside 2.6 OpenVZ container.”

Leave a Comment

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