So I needed to upgrade my home "web hosting" server from a Raspberry Pi 3b to something more flexible where I could even simulate a Raspberry Pi 3b given power. The new server hardware is now an Intel NUC i7 16GB / 250Gb SSD NVME. π
I order to accomplish this task I had to find a way to bridge the wireless interface which is the faster one on my actual home network setup.
I've also tried to mix the functionnality from another Rapsberry Pi (3b+ this time) who's acting as WLAN to LAN bridge. More details on this setup. But this was finally a bad idea and I was not able to make it work along the virtual network bridge created by libvirt or manually created... (I will explain why later)
The main difficulty was to use the DMZ IP address given by the router and route the traffic to the guest VM's.
The process will be explained for both server and desktop installations.
The following will describe the required steps for configuring your virtual host server.
For desktop installation, this is already covered here.
The server installation require less packages than the desktop one.
sudo apt install virt-manager libvirt-bin qemuIf the displayed dependency list is too big, cancel with
Ctrl+Cand retry without the packagevirt-manager.
Reboot to complete the installation.
Starting from 18.04, the network stack is now managed by netplan.io and network config has to be written in YAML language in /etc/netplan/01-network.yaml for example.
The network configuration will be read from the /etc/netplan directory and will lookup for *.yaml files.
On desktop installation, netplan will write config files for NetworkManager but for this project, it was not needed finally, I've just disabled the LAN interface and configured the wireless interface using NetworkManager.
On server installation, you can decide between systemd-networkd and NetworkManager backends. Both should work but NetworkManager renderer might be more complicated to manage on servers.
# This file is generated from information provided by
# the datasource. Changes to it will not persist across an instance.
# To disable cloud-init's network configuration capabilities, write a file
# /etc/cloud/cloud.cfg.d/99-disable-network-config.cfg with the following:
# network: {config: disabled}
network:
version: 2
renderer: networkd
#renderer: NetworkManager
ethernets:
eth0:
optional: true
dhcp4: false
dhcp6: false
wifis:
wlan0:
optional: true
access-points:
"YOUR-SSID-NAME":
password: "YOUR-PASSWORD"
dhcp4: true
#dhcp-identifier: mac # uncomment this line if you're using a Microsoft DHCP ServerThis will left LAN interface UP without IP address assigned (if not, remove the whole
ethernetsblock and reboot.) and the wireless interace UP with IP assigned from your local DHCP server.
Once you have defined your network configuration in the YAML file, there are command lines to run.
To try your new configuration before applying to see if there is no errors:
sudo netplan --debug tryIf there is no errors, then you can generate related configuration files:
sudo netplan --debug generateOnce done, you can apply your new network configuration:
sudo netplan --debug applyOkay, this was the most difficult part but no so difficult when you finally understand all the related concepts... π
The following is designed to work with NAT'ed virtual switches but it will also work for Routed'ed ones.
You can dit from both virt-manager or virsh command. virt-manager would be more designed for desktop installation.
Here is the dumped XML configuration used.
For the NAT version:
virsh net-dumpxml test-nated<network connections='1'>
<name>test-nated</name>
<uuid>79cbec68-135e-4cb2-8272-3ffbf1477740</uuid>
<forward dev='wlp58s0' mode='nat'>
<nat>
<port start='1024' end='65535'/>
</nat>
<interface dev='wlp58s0'/>
</forward>
<bridge name='virbr1' stp='on' delay='0'/>
<mac address='52:54:00:d3:87:9e'/>
<ip address='192.168.REDACTED.1' netmask='255.255.255.0'>
<dhcp>
<range start='192.168.REDACTED.REDACTED' end='192.168.REDACTED.REDACTED'/>
</dhcp>
</ip>
</network>For the Routed version:
virsh net-dumpxml test-routed<network>
<name>test-routed</name>
<uuid>ccc336d3-7637-4d85-9281-c185503f4798</uuid>
<forward dev='wlp58s0' mode='route'>
<interface dev='wlp58s0'/>
</forward>
<bridge name='virbr2' stp='on' delay='0'/>
<mac address='52:54:00:91:af:bd'/>
<ip address='192.168.REDACTED.1' netmask='255.255.255.0'>
<dhcp>
<range start='192.168.REDACTED.REDACTED' end='192.168.REDACTED.REDACTED'/>
</dhcp>
</ip>
</network>This is necessary is order to get all the IPv4 traffic forwarded to all interfaces.
You can also enable the
IPv6traffic forwarding by changingipv4byipv6below.
echo /proc/sys/net/ipv4/ip_forward'0' means
disabledand '1' meansenabled.
sudo su -c 'echo 1 > /proc/sys/net/ipv4/ip_forward''0' to
disableand '1' toenable.
sudo sysctl -w net.ipv4.ip_forward=1'0' to
disableand '1' toenable.
This should be already applied by libvirt but if not, you know how now. π
libvirt will use iptables to setup the POST/PRE routing tables, the hook will be used in order to setup required tables for each guest VM's pointing to the DMZ IP address.
#!/bin/bash
# IMPORTANT: Change the "VM NAME" string to match your actual VM Name.
# In order to create rules to other VMs, just duplicate the below block and configure
# it accordingly.
if [ "${1}" = "low-srv-vm" ]; then
# Update the following variables to fit your setup
BRIDGE_IFACE=virbr1
HOST_IP=192.168.REDACTED.REDACTED
GUEST_IP=192.168.REDACTED.REDACTED
GUEST_PORT=
HOST_PORT=
if [ "${2}" = "stopped" ] || [ "${2}" = "reconnect" ]; then
/sbin/iptables -D FORWARD -o $BRIDGE_IFACE -d $GUEST_IP -j ACCEPT
#/sbin/iptables -t nat -D PREROUTING -p tcp --dport $HOST_PORT -j DNAT --to $GUEST_IP:$GUEST_PORT
/sbin/iptables -t nat -D PREROUTING -d $HOST_IP -j DNAT --to-destination $GUEST_IP
/sbin/iptables -t nat -D POSTROUTING -s $GUEST_IP -j SNAT --to-source $HOST_IP
fi
if [ "${2}" = "start" ] || [ "${2}" = "reconnect" ]; then
/sbin/iptables -I FORWARD -o $BRIDGE_IFACE -d $GUEST_IP -j ACCEPT
#/sbin/iptables -t nat -I PREROUTING -p tcp --dport $HOST_PORT -j DNAT --to $GUEST_IP:$GUEST_PORT
/sbin/iptables -t nat -A PREROUTING -d $HOST_IP -j DNAT --to-destination $GUEST_IP
/sbin/iptables -t nat -A POSTROUTING -s $GUEST_IP -j SNAT --to-source $HOST_IP
fi
fi
if [ "${1}" = "high-srv-vm" ]; then
# Update the following variables to fit your setup
BRIDGE_IFACE=virbr1
HOST_IP=192.168.REDACTED.REDACTED
GUEST_IP=192.168.REDACTED.REDACTED
GUEST_PORT=
HOST_PORT=
if [ "${2}" = "stopped" ] || [ "${2}" = "reconnect" ]; then
/sbin/iptables -D FORWARD -o $BRIDGE_IFACE -d $GUEST_IP -j ACCEPT
#/sbin/iptables -t nat -D PREROUTING -p tcp --dport $HOST_PORT -j DNAT --to $GUEST_IP:$GUEST_PORT
/sbin/iptables -t nat -D PREROUTING -d $HOST_IP -j DNAT --to-destination $GUEST_IP
/sbin/iptables -t nat -D POSTROUTING -s $GUEST_IP -j SNAT --to-source $HOST_IP
fi
if [ "${2}" = "start" ] || [ "${2}" = "reconnect" ]; then
/sbin/iptables -I FORWARD -o $BRIDGE_IFACE -d $GUEST_IP -j ACCEPT
#/sbin/iptables -t nat -I PREROUTING -p tcp --dport $HOST_PORT -j DNAT --to $GUEST_IP:$GUEST_PORT
/sbin/iptables -t nat -A PREROUTING -d $HOST_IP -j DNAT --to-destination $GUEST_IP
/sbin/iptables -t nat -A POSTROUTING -s $GUEST_IP -j SNAT --to-source $HOST_IP
fi
fiThis is a modified version from the one found here: https://wiki.libvirt.org/page/Networking#Forwarding_Incoming_Connections
Write this and modify it in /etc/libvirt/hooks/qemu file.
If you want to
NATusingportsinstead ofIPaddress, just defineGUEST_PORTandHOST_PORTvariables and uncomment the second line in eachifblocks.Comment the two last lines in each
ifblocks.
sudo nano /etc/libvirt/hooks/qemuThen close all running gues VM's and restart the libvirtd service to apply the new defined hook.
sudo systemctl restart libvirtdIf you are using
virt-manageryou will have to reconnect to theqemuserver, justdbl-clickon it. (see pictures)
Now restart the guest VM linked to the DMZ address.
I was not able to make this working with more than one guest VM linked to the
DMZIP address... I may try to add a new intermediary VM that will act as aload-balancerand decide where to push traffic so I could keep both gues VM's online and linked to theDMZIP address! π€
To resume, you should have something like the following as network configuration.
Show network links:
ip -s -s -c l1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
RX: bytes packets errors dropped overrun mcast
8420207 138864 0 0 0 0
RX errors: length crc frame fifo missed
0 0 0 0 0
TX: bytes packets errors dropped carrier collsns
8420207 138864 0 0 0 0
TX errors: aborted fifo window heartbeat transns
0 0 0 0 0
2: eno1: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc fq_codel state DOWN mode DEFAULT group default qlen 1000
link/ether f4:4d:30:6d:9b:2f brd ff:ff:ff:ff:ff:ff
RX: bytes packets errors dropped overrun mcast
0 0 0 0 0 0
RX errors: length crc frame fifo missed
0 0 0 0 0
TX: bytes packets errors dropped carrier collsns
0 0 0 0 0 0
TX errors: aborted fifo window heartbeat transns
0 0 0 0 1
3: wlp58s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP mode DORMANT group default qlen 1000
link/ether f8:63:3f:3a:eb:1b brd ff:ff:ff:ff:ff:ff
RX: bytes packets errors dropped overrun mcast
2626462996 1941220 0 0 0 0
RX errors: length crc frame fifo missed
0 0 0 0 0
TX: bytes packets errors dropped carrier collsns
26234421 210183 0 0 0 0
TX errors: aborted fifo window heartbeat transns
0 0 0 0 2
4: virbr2: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN mode DEFAULT group default qlen 1000
link/ether 52:54:00:91:af:bd brd ff:ff:ff:ff:ff:ff
RX: bytes packets errors dropped overrun mcast
0 0 0 0 0 0
RX errors: length crc frame fifo missed
0 0 0 0 0
TX: bytes packets errors dropped carrier collsns
0 0 0 0 0 0
TX errors: aborted fifo window heartbeat transns
0 0 0 0 1
5: virbr2-nic: <BROADCAST,MULTICAST> mtu 1500 qdisc fq_codel master virbr2 state DOWN mode DEFAULT group default qlen 1000
link/ether 52:54:00:91:af:bd brd ff:ff:ff:ff:ff:ff
RX: bytes packets errors dropped overrun mcast
0 0 0 0 0 0
RX errors: length crc frame fifo missed
0 0 0 0 0
TX: bytes packets errors dropped carrier collsns
0 0 0 0 0 0
TX errors: aborted fifo window heartbeat transns
0 0 0 0 1
6: virbr1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DEFAULT group default qlen 1000
link/ether 52:54:00:d3:87:9e brd ff:ff:ff:ff:ff:ff
RX: bytes packets errors dropped overrun mcast
131446567 439317 0 0 0 0
RX errors: length crc frame fifo missed
0 0 0 0 0
TX: bytes packets errors dropped carrier collsns
2418206543 277695 0 0 0 0
TX errors: aborted fifo window heartbeat transns
0 0 0 0 4
7: virbr1-nic: <BROADCAST,MULTICAST> mtu 1500 qdisc fq_codel master virbr1 state DOWN mode DEFAULT group default qlen 1000
link/ether 52:54:00:d3:87:9e brd ff:ff:ff:ff:ff:ff
RX: bytes packets errors dropped overrun mcast
0 0 0 0 0 0
RX errors: length crc frame fifo missed
0 0 0 0 0
TX: bytes packets errors dropped carrier collsns
0 0 0 0 0 0
TX errors: aborted fifo window heartbeat transns
0 0 0 0 1
9: vnet0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel master virbr1 state UNKNOWN mode DEFAULT group default qlen 1000
link/ether fe:54:00:d9:e1:a7 brd ff:ff:ff:ff:ff:ff
RX: bytes packets errors dropped overrun mcast
137585811 439269 0 0 0 0
RX errors: length crc frame fifo missed
0 0 0 0 0
TX: bytes packets errors dropped carrier collsns
2418728374 287718 0 0 0 0
TX errors: aborted fifo window heartbeat transns
0 0 0 0 0 Show network addresses:
ip -s -s -c a1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
RX: bytes packets errors dropped overrun mcast
8452947 139400 0 0 0 0
RX errors: length crc frame fifo missed
0 0 0 0 0
TX: bytes packets errors dropped carrier collsns
8452947 139400 0 0 0 0
TX errors: aborted fifo window heartbeat transns
0 0 0 0 0
2: eno1: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc fq_codel state DOWN group default qlen 1000
link/ether f4:4d:30:6d:9b:2f brd ff:ff:ff:ff:ff:ff
RX: bytes packets errors dropped overrun mcast
0 0 0 0 0 0
RX errors: length crc frame fifo missed
0 0 0 0 0
TX: bytes packets errors dropped carrier collsns
0 0 0 0 0 0
TX errors: aborted fifo window heartbeat transns
0 0 0 0 1
3: wlp58s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
link/ether f8:63:3f:3a:eb:1b brd ff:ff:ff:ff:ff:ff
inet 192.168.REDACTED.REDACTED/24 brd 192.168.REDACTED.255 scope global dynamic noprefixroute wlp58s0
valid_lft 1476sec preferred_lft 1476sec
inet6 fe80::fa63:3fff:fe3a:eb1b/64 scope link
valid_lft forever preferred_lft forever
RX: bytes packets errors dropped overrun mcast
2626488340 1941523 0 0 0 0
RX errors: length crc frame fifo missed
0 0 0 0 0
TX: bytes packets errors dropped carrier collsns
26243920 210243 0 0 0 0
TX errors: aborted fifo window heartbeat transns
0 0 0 0 2
4: virbr2: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default qlen 1000
link/ether 52:54:00:91:af:bd brd ff:ff:ff:ff:ff:ff
inet 192.168.REDACTED.1/24 brd 192.168.REDACTED.255 scope global virbr2
valid_lft forever preferred_lft forever
RX: bytes packets errors dropped overrun mcast
0 0 0 0 0 0
RX errors: length crc frame fifo missed
0 0 0 0 0
TX: bytes packets errors dropped carrier collsns
0 0 0 0 0 0
TX errors: aborted fifo window heartbeat transns
0 0 0 0 1
5: virbr2-nic: <BROADCAST,MULTICAST> mtu 1500 qdisc fq_codel master virbr2 state DOWN group default qlen 1000
link/ether 52:54:00:91:af:bd brd ff:ff:ff:ff:ff:ff
RX: bytes packets errors dropped overrun mcast
0 0 0 0 0 0
RX errors: length crc frame fifo missed
0 0 0 0 0
TX: bytes packets errors dropped carrier collsns
0 0 0 0 0 0
TX errors: aborted fifo window heartbeat transns
0 0 0 0 1
6: virbr1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
link/ether 52:54:00:d3:87:9e brd ff:ff:ff:ff:ff:ff
inet 192.168.REDACTED.1/24 brd 192.168.REDACTED.255 scope global virbr1
valid_lft forever preferred_lft forever
RX: bytes packets errors dropped overrun mcast
131462225 439370 0 0 0 0
RX errors: length crc frame fifo missed
0 0 0 0 0
TX: bytes packets errors dropped carrier collsns
2418210827 277752 0 0 0 0
TX errors: aborted fifo window heartbeat transns
0 0 0 0 4
7: virbr1-nic: <BROADCAST,MULTICAST> mtu 1500 qdisc fq_codel master virbr1 state DOWN group default qlen 1000
link/ether 52:54:00:d3:87:9e brd ff:ff:ff:ff:ff:ff
RX: bytes packets errors dropped overrun mcast
0 0 0 0 0 0
RX errors: length crc frame fifo missed
0 0 0 0 0
TX: bytes packets errors dropped carrier collsns
0 0 0 0 0 0
TX errors: aborted fifo window heartbeat transns
0 0 0 0 1
9: vnet0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel master virbr1 state UNKNOWN group default qlen 1000
link/ether fe:54:00:d9:e1:a7 brd ff:ff:ff:ff:ff:ff
inet6 fe80::fc54:ff:fed9:e1a7/64 scope link
valid_lft forever preferred_lft forever
RX: bytes packets errors dropped overrun mcast
137602211 439322 0 0 0 0
RX errors: length crc frame fifo missed
0 0 0 0 0
TX: bytes packets errors dropped carrier collsns
2418734374 287808 0 0 0 0
TX errors: aborted fifo window heartbeat transns
0 0 0 0 0 Show network routes:
ip -s -s -c rdefault via 192.168.REDACTED.1 dev wlp58s0 proto dhcp metric 600
169.254.0.0/16 dev virbr2 scope link metric 1000 linkdown
192.168.REDACTED.0/24 dev virbr2 proto kernel scope link src 192.168.REDACTED.1 linkdown
192.168.REDACTED.0/24 dev virbr1 proto kernel scope link src 192.168.REDACTED.1
192.168.REDACTED.0/24 dev wlp58s0 proto kernel scope link src 192.168.REDACTED.REDACTED metric 600 Show network configuration:
cat /etc/netplan/01-network.yamlIt can also be named as
50-cloud-init.yamlon Ubuntu Server 18.04
# This file is generated from information provided by
# the datasource. Changes to it will not persist across an instance.
# To disable cloud-init's network configuration capabilities, write a file
# /etc/cloud/cloud.cfg.d/99-disable-network-config.cfg with the following:
# network: {config: disabled}
network:
version: 2
renderer: networkd
#renderer: NetworkManager
#ethernets:
# eth0:
# optional: true
# dhcp4: false
# dhcp6: false
wifis:
wlan0:
optional: true
access-points:
"YOUR-SSID-NAME":
password: "YOUR-PASSWORD"
dhcp4: true
#dhcp-identifier: mac # uncomment this line if you're using a Microsoft DHCP ServerTo resume, you should have something like the following as network configuration.
Show network links:
ip -s -s -c l1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
RX: bytes packets errors dropped overrun mcast
798805 2363 0 0 0 0
RX errors: length crc frame fifo missed
0 0 0 0 0
TX: bytes packets errors dropped carrier collsns
798805 2363 0 0 0 0
TX errors: aborted fifo window heartbeat transns
0 0 0 0 0
2: ens3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP mode DEFAULT group default qlen 1000
link/ether 52:54:00:d9:e1:a7 brd ff:ff:ff:ff:ff:ff
RX: bytes packets errors dropped overrun mcast
2418806941 288925 0 3674 0 0
RX errors: length crc frame fifo missed
0 0 0 0 0
TX: bytes packets errors dropped carrier collsns
137819192 440031 0 0 0 0
TX errors: aborted fifo window heartbeat transns
0 0 0 0 2 Show network addresses:
ip -s -s -c a1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
RX: bytes packets errors dropped overrun mcast
798805 2363 0 0 0 0
RX errors: length crc frame fifo missed
0 0 0 0 0
TX: bytes packets errors dropped carrier collsns
798805 2363 0 0 0 0
TX errors: aborted fifo window heartbeat transns
0 0 0 0 0
2: ens3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
link/ether 52:54:00:d9:e1:a7 brd ff:ff:ff:ff:ff:ff
inet 192.168.REDACTED.REDACTED/24 brd 192.168.REDACTED.255 scope global dynamic ens3
valid_lft 2585sec preferred_lft 2585sec
inet6 fe80::5054:ff:fed9:e1a7/64 scope link
valid_lft forever preferred_lft forever
RX: bytes packets errors dropped overrun mcast
2418807871 288937 0 3675 0 0
RX errors: length crc frame fifo missed
0 0 0 0 0
TX: bytes packets errors dropped carrier collsns
137821330 440038 0 0 0 0
TX errors: aborted fifo window heartbeat transns
0 0 0 0 2 Show network routes:
ip -s -s -c rdefault via 192.168.REDACTED.1 dev ens3 proto dhcp src 192.168.REDACTED.REDACTED metric 100
192.168.REDACTED.0/24 dev ens3 proto kernel scope link src 192.168.REDACTED.REDACTED
192.168.REDACTED.1 dev ens3 proto dhcp scope link src 192.168.REDACTED.REDACTED metric 100Show network configuration:
cat /etc/netplan/01-netcfg.yaml# This file describes the network interfaces available on your system
# For more information, see netplan(5).
network:
version: 2
renderer: networkd
ethernets:
ens3:
dhcp4: yesSo after all this work done, we need to be sure that everything will be kept on reboots and be functional, so we will reboot now.
sudo rebootor:
systemctl rebootThen... Pray! π
To verify if everything was working correctly I just tried to reach my personal DNS domain (well not really mine to be honest, I'm using https://freedns.afraid.org/)
To reach the server: http://jiab77.dyn.ch
I wanted to know my knew hosting speed compared to what I could with my previous setup on Raspberry Pi's (server + bridge)
- Using a small custom one: http://jiab77.dyn.ch/speed.php
- Using Google
Insights: https://developers.google.com/speed/pagespeed/insights/?url=http%3A%2F%2Fjiab77.dyn.ch%2F - Using WebPageTest: https://www.webpagetest.org/result/190702_BP_83a45ba547a25749b9ae8c98e33b5456/
The custom
speedtestmight be deleted from the server later.
Some bonus because I think they might interest you π
In order to proceed to different performance testing, I don't really want to have to copy all data files between all my test VM's so I've decided to use a shared folder with 9p.
For more details, see both pages: http://www.linux-kvm.org/page/9p_virtio and https://wiki.qemu.org/Documentation/9psetup.
I've planned to use the passthrough mode to have the best performance.
I thought that would not be difficult to put in place... Guess what?! I was wrong! π
There is two methods to load the required module in the kernel, I will use both of them but I think you can use only one method.
In my case I've decided the following:
- Put them directly in the host kernel image
- Loading them dynamicaly on the guest VM
lsmod | grep 9pIf the output is empty on both
hostandguest, then you have to load the required modules.
sudo -scat >>/etc/initramfs-tools/modules <<EOF
9p
9pnet
9pnet_virtio
EOFsudo update-initramfs -uk allThen reboot to load the new kernel image.
sudo -scat >>/etc/modules <<EOF
9p
9pnet
9pnet_virtio
EOFThen reboot to load the new kernel modules.
If using only one method does not work for you, try while using my setup.
In order to give access to the account libvirt-qemu on your system, you will have to do some minor changes on it. I choose the method that gives the minimal required permissions and also the minimal required system changes. Other methods are described in reference links.
This will have the minimal impact regarding the system changes that has to be done.
# Create your shared folder
cd ~/
mkdir -v shared
# Assign file-system permissions
chmod -v 777 sharedStart with the maximal permissions then decrease according to your needs. The goal is to avoid all possible issues during the first mount. Normally
755should be enougth.
This will have a bigger impact regarding the system changes that has to be done. This is because you will have to grant access to all content located in /media/user. As I need to use my second hard drive mounted in /media/user/disk, I've used this method.
# Create your shared folder
cd /media/user/disk
sudo mkdir -v shared
# Grant access to libvirt-qemu account in ACL's
sudo setfacl -R -m u:libvirt-qemu:rwx /media/user
# Assign file-system permissions
sudo chmod -v 755 /media/user/disk/sharedI had to use
sudoin my case because everything mounted in/media/user/is mounted asroot. So my normal user account can't make any changes.
Now you should have everything ready so you should be able to map your shared folder and run your guest VM without any troubles. (not like me π )
The
Target Pathis not really apathit is in fact atagthat will be used on theguestside to identify the shared folder.
Choose the Access Mode that correspond to your needs. In my case I've used the mapped mode, so host and guest must use the same user to access or make change on the shared folder.
This will define how file-system permissions will be written on the shared folder from the guest side to the host side. According to the documentation this work as follow:
The filesystem block has an optional attribute accessmode which specifies the security mode for accessing the source (since 0.8.5). Currently this only works with type='mount' for the QEMU/KVM driver. The possible values are:
passthrough: The source is accessed with the permissions of the user inside the guest. This is the default accessmode if one is not specified. More info. Beware that changes to permissions/ownership will affect all guests using that filesystem. This mode is generally quite fast.mapped: The source is accessed with the permissions of the hypervisor (QEMU process). More info. This means you need to make sure that files on the hypervisor are accessible to the QEMU process (username libvirt-qemu on my setup). The advantage is that file attributes and permissions are "mapped" for the guest so that they are independent changes elsewhere (as long as the files stay accessible). If your host system supports ACLs, this mode will also allow proper ACL support in the guest. This mode is generally a bit slower than passthrough.squash: Similar to 'passthrough', the exception is that failure of privileged operations like 'chown' are ignored. This makes a passthrough-like mode usable for people who run the hypervisor as non-root. More infoReferences:
Once the VM is started, you will have to mount your newly attached folder. Again, two methods to proceed:
sudo mkdir -v /tmp/shared
sudo mount -v -t 9p -o trans=virtio,version=9p2000.L shared /tmp/shared
mount: shared mounted on /tmp/shared.sudo mkdir -v /mnt/shared
echo 'shared /mnt/shared 9p trans=virtio,version=9p2000.L,rw 0 0' | sudo tee -a /etc/fstabBeware that if you mistype the shared folder name, the system will crash on boot...
Other observations:
Even if it is mounted in
read/writemode because ofrw, is it theAccess Modethat will define the real access. But you can restrict the access even more by changingrwtoroto mount the shared folder inread-onlymode.
I've planned to use netdata to get realtime server status on every guest VM's and physical servers.
Very simple, just run the script and follow instructions.
bash <(curl -Ss https://my-netdata.io/kickstart.sh)Run without using
sudo.
Once finished just scroll up to see if you get a message like this:
Memory de-duplication instructions
You have kernel memory de-duper (called Kernel Same-page Merging,
or KSM) available, but it is not currently enabled.
To enable it run:
echo 1 >/sys/kernel/mm/ksm/run
echo 1000 >/sys/kernel/mm/ksm/sleep_millisecs
If you enable it, you will save 40-60% of netdata memory.Proceed as explained.
Using
sudo:sudo su -c 'echo 1000 >/sys/kernel/mm/ksm/sleep_millisecs' sudo su -c 'echo 1 >/sys/kernel/mm/ksm/run'Should make it work.
Now you can check your server stats by using http://your-ip-address:19999. In my case, the guest VM IP address.
If you want to know more about netdata, check the documentation or the project itself.
As my host defined as virtualization server, it will "see" all the traffic coming from the DMZ IP address, so to have a better look of what's going on the pipe π I've planned to use Ntop-ng.
I've already covered this part in another gist: https://gist.github.com/Jiab77/023bbe036d7f60008ecd044c9a61591c
After the installation I've seen that Ntop-ng was complaining about GRO, GSO and TSO, I don't really know what are they but if you want to get rid of this consistent message, just power on your guest VM's and run on your host server:
# First VM
sudo ethtool -K vnet0 gro off gso off tso off
# Second VM
sudo ethtool -K vnet1 gro off gso off tso offDo this on every
vnetXinterfaces you have.
Feel free to contribute by giving new ideas, fixes, or anything you would consider useful by posting a comment to this gist.
Some very helpful references that helped me to finally my it work after more than a week of fighting π .
- https://baturin.org/docs/iproute2/
- https://wiki.libvirt.org/page/Networking#Forwarding_Incoming_Connections
- https://libvirt.org/formatnetwork.html
- https://wiki.libvirt.org/page/Networking
- https://wiki.libvirt.org/page/VirtualNetworking
- https://unix.stackexchange.com/questions/159191/setup-kvm-on-a-wireless-interface-on-a-laptop-machine
- https://unix.stackexchange.com/questions/118891/wireless-bridged-networking-in-kvm-why-is-it-so-complicated
- https://unix.stackexchange.com/questions/8673/bridged-networking-with-kvm
- https://help.ubuntu.com/community/KVM/Networking#bridgednetworking
- http://www.linux-kvm.org/page/Networking#public_bridge
- http://www.linux-kvm.org/page/9p_virtio
- https://wiki.qemu.org/Documentation/9psetup
- https://forums.unraid.net/topic/34691-9p-sharing-speed-not-what-i-expected/
- http://www.linux-kvm.org/page/9p_virtio
- https://wiki.qemu.org/Documentation/9psetup
- http://rabexc.org/posts/p9-setup-in-libvirt
- http://troglobit.com/2013/07/05/file-system-pass-through-in-kvm-slash-qemu-slash-libvirt/
- https://askubuntu.com/questions/772784/9p-libvirt-qemu-share-modes
- https://stackoverflow.com/questions/52591115/virtio-9p-failed-to-initialize-fs-driver-when-i-share-folder-between-kvm-host
- https://superuser.com/questions/1317119/qemu-share-folder-9pnet-virtio-no-channels-available-for-device/1412037#1412037
- https://askubuntu.com/questions/548208/sharing-folder-with-vm-through-libvirt-9p-permission-denied
- https://superuser.com/questions/502205/libvirt-9p-kvm-mount-in-fstab-fails-to-mount-at-boot-time
You can reach me on Twitter by using: @Jiab77
Just because I've tried to provide two main features:
- Replace my Raspberry Pi based
webserver. - Replace my Raspberry Pi based WLAN / LAN
bridge.
So I've tried many things like:
- Create a pseudo-ethernet interface using
macvlantype. - Create a dummy ethernet interface using
dummytype. - Create a virtual ethernet interface using
vethtype. - Create a bridge interface using
bridgetype and:- Map
LANinterface to thebridge - Map
WLANinterface to thebridge - Map any othe the newly created interface to the bridge
- Map
and each time I've assigned the DMZ IP address to the newly created interface.
All of this worked but created network issues:
- No more WLAN / LAN communication once the
bridgebringing UP...- No more external access on guest VM's
- No more
DNSresolution on guest VM's- No more IP given by the
libvirtvirtual switch...- And so many other issues... π













Added pictures.