Time to carry on with the changes to set up the machine correctly. Here is a TLDR of this entry
- Setup a bridge device - no problems
- Setup time synchronisation - no problems
- Setup kvm - a bit of back and forth about a installing the monolithic daemon
vs using separate daemons, but then deciding to go with the monolith. Also learned
that I need to install
dmidecodeanddnsmasqas well so that the monolithic daemon is not complaining. - Setup dnsmasq and NAT on the host - learned that masquerading is only needed on the outgoing interface only.
Setup an ethernet bridge for Virtual Machines
[matelakat@homes ~]$ sudo tee -a /etc/systemd/network/pubbr.netdev << EOF
[NetDev]
Name=pubbr
Kind=bridge
EOF
[matelakat@homes ~]$ sudo tee /etc/systemd/network/pubbr.network << EOF
[Match]
Name=pubbr
[Network]
Address=192.168.115.1/24
ConfigureWithoutCarrier=yes
EOF
Reloading Configuration and getting a status
[root@homes ~]# networkctl reload
[root@homes ~]# networkctl
IDX LINK TYPE OPERATIONAL SETUP
1 lo loopback carrier unmanaged
2 wired0 ether routable configured
3 pubbr bridge no-carrier configured
3 links listed.
Setup Time Synchronisation on the Host
First is to check the situation:
[root@homes ~]# timedatectl show --all
Timezone=Europe/Budapest
LocalRTC=no
CanNTP=yes
NTP=no
NTPSynchronized=no
TimeUSec=Sat 2026-01-17 10:51:58 CET
RTCTimeUSec=Sat 2026-01-17 10:51:58 CET
Configure NTP
[matelakat@homes ~]$ sudo tee /etc/systemd/timesyncd.conf << EOF
[Time]
NTP=0.hu.pool.ntp.org 1.hu.pool.ntp.org 2.hu.pool.ntp.org 3.hu.pool.ntp.org
FallbackNTP=0.hu.pool.ntp.org 1.hu.pool.ntp.org 2.hu.pool.ntp.org 3.hu.pool.ntp.org
EOF
Then start and enable it:
[matelakat@homes ~]$ sudo systemctl enable --now systemd-timesyncd
Check
[matelakat@homes ~]$ timedatectl show --all
Timezone=Europe/Budapest
LocalRTC=no
CanNTP=yes
NTP=yes
NTPSynchronized=yes
TimeUSec=Sat 2026-01-17 11:09:58 CET
RTCTimeUSec=Sat 2026-01-17 11:09:58 CET
Setup kvm
[matelakat@homes ~]$ sudo pacman -S libvirt qemu-full openbsd-netcat
I picked the default option for audio provider, jack2
Adding myself to the group and enabling KVM:
[matelakat@homes ~]$ sudo gpasswd --add matelakat libvirt
[matelakat@homes ~]$ sudo systemctl enable --now libvirtd.service
# sudo gpasswd --add matelakat libvirt
# sudo systemctl enable --now libvirtd.service
Output was something along the lines of:
Created symlink '/etc/systemd/system/multi-user.target.wants/libvirtd.service' → '/usr/lib/systemd/system/libvirtd.service'.
Created symlink '/etc/systemd/system/sockets.target.wants/virtlockd.socket' → '/usr/lib/systemd/system/virtlockd.socket'.
Created symlink '/etc/systemd/system/sockets.target.wants/virtlogd.socket' → '/usr/lib/systemd/system/virtlogd.socket'.
Created symlink '/etc/systemd/system/sockets.target.wants/libvirtd.socket' → '/usr/lib/systemd/system/libvirtd.socket'.
Created symlink '/etc/systemd/system/sockets.target.wants/libvirtd-ro.socket' → '/usr/lib/systemd/system/libvirtd-ro.socket'.
Created symlink '/etc/systemd/system/sockets.target.wants/libvirtd-admin.socket' → '/usr/lib/systemd/system/libvirtd-admin.socket'.
Created symlink '/etc/systemd/system/sockets.target.wants/virtlockd-admin.socket' → '/usr/lib/systemd/system/virtlockd-admin.socket'.
Created symlink '/etc/systemd/system/sockets.target.wants/virtlogd-admin.socket' → '/usr/lib/systemd/system/virtlogd-admin.socket'.
I am seeing interesting messages:
[matelakat@homes ~]$ systemctl status libvirtd
● libvirtd.service - libvirt legacy monolithic daemon
Loaded: loaded (/u
sr/lib/systemd/system/libvirtd.service; enabled; preset:
disabled)
Active: active (running) since Sat 2026-01-17 11:18:09 CET; 1min
36s ago
Invocation: d1347c8d619a486a8b5322c96c14e33c
TriggeredBy: ● libvirtd.socket
● libvirtd-admin.socket
● libvirtd-ro.socket
Docs: man:libvirtd(8)
https://libvirt.org/
Main PID: 2415 (libvirtd)
Tasks: 21 (limit: 32768)
Memory: 31.7M (peak: 31.8M)
CPU: 180ms
CGroup: /system.slice/libvirtd.service
└─2415 /usr/bin/libvirtd --timeout 120
Jan 17 11:18:09 homes systemd[1]: Starting libvirt legacy monolithic daemon...
Jan 17 11:18:09 homes systemd[1]: Started libvirt legacy monolithic daemon.
Jan 17 11:18:09 homes libvirtd[2415]: libvirt version: 12.0.0
Jan 17 11:18:09 homes libvirtd[2415]: hostname: homes
Jan 17 11:18:09 homes libvirtd[2415]: Unable to find 'dn
smasq' binary in $PATH: No such file or directory
Jan 17 11:18:09 homes libvirtd[2415]: Cannot find 'dmide
code' in path: No such file or directory
Jan 17 11:18:09 homes libvirtd[2415]: Cannot find 'dmide
code' in path: No such file or directory
What I am worried about is that this is called "legacy" and also the non-found pieces. So let me learn something new.
Ok, so it seems I do not need to enable the one big monolithic process anymore, so disabling that:
[matelakat@homes ~]$ sudo systemctl stop libvirtd.service
Stopping 'libvirtd.service', but its triggering units are still active:
libvirtd.socket, libvirtd-admin.socket, libvirtd-ro.socket
[matelakat@homes ~]$ sudo systemctl disable libvirtd.service
Removed '/etc/systemd/system/multi-user.target.wants/libvirtd.service'.
Removed '/etc/systemd/system/sockets.target.wants/virtlockd-admin.socket'.
Removed '/etc/systemd/system/sockets.target.wants/virtlogd-admin.socket'.
Removed '/etc/systemd/system/sockets.target.wants/libvirtd-ro.socket'.
Removed '/etc/systemd/system/sockets.target.wants/virtlogd.socket'.
Removed '/etc/systemd/system/sockets.target.wants/virtlockd.socket'.
Removed '/etc/systemd/system/sockets.target.wants/libvirtd.socket'.
Removed '/etc/systemd/system/sockets.target.wants/libvirtd-admin.socket'.
Disabling 'libvirtd.service', but its triggering units are still active:
libvirtd.socket, libvirtd-admin.socket, libvirtd-ro.socket
I wonder what it means. It means that though I disabled a service, it still can be activated and thus brought up by other services.
So to completely disable that I would need to disable the triggering ones as well.
Did this:
[matelakat@homes ~]$ sudo systemctl disable --now \
libvirtd.service \
libvirtd.socket \
libvirtd-admin.socket \
libvirtd-ro.socket
And that was still printing out the same story, but running it the second time
it didn't. I guess when it was disabling libvirtd.service, the other sockets
were still active.
Ok, so how do I do the modern approach, where I do not need to run anything that is legacy?
Ok, I decided to ignore this monolithic nature of the hypervisor, and instead I will just simply use the monolithic approach for now:
[matelakat@homes ~]$ sudo systemctl start libvirtd.service
[matelakat@homes ~]$ sudo systemctl start virtlogd.service
[matelakat@homes ~]$ sudo systemctl enable libvirtd.service
Created symlink '/etc/systemd/system/multi-user.target.wants/libvirtd.service' → '/usr/lib/systemd/system/libvirtd.service'.
Created symlink '/etc/systemd/system/sockets.target.wants/virtlockd.socket' → '/usr/lib/systemd/system/virtlockd.socket'.
Created symlink '/etc/systemd/system/sockets.target.wants/virtlogd.socket' → '/usr/lib/systemd/system/virtlogd.socket'.
Created symlink '/etc/systemd/system/sockets.target.wants/libvirtd.socket' → '/usr/lib/systemd/system/libvirtd.socket'.
Created symlink '/etc/systemd/system/sockets.target.wants/libvirtd-ro.socket' → '/usr/lib/systemd/system/libvirtd-ro.socket'.
Created symlink '/etc/systemd/system/sockets.target.wants/libvirtd-admin.socket' → '/usr/lib/systemd/system/libvirtd-admin.socket'.
Created symlink '/etc/systemd/system/sockets.target.wants/virtlockd-admin.socket' → '/usr/lib/systemd/system/virtlockd-admin.socket'.
Created symlink '/etc/systemd/system/sockets.target.wants/virtlogd-admin.socket' → '/usr/lib/systemd/system/virtlogd-admin.socket'.
Okay, let's see what I have now.
[matelakat@homes ~]$ virsh list --all
Id Name State
--------------------
That is nice. Now let me see if I can connect to it remotely with virt-manager.
It failed. The message is as follows:
Unable to connect to libvirt qemu+ssh://matelakat@homes/system.
Configure SSH key access for the remote host, or install an SSH askpass package locally.
Libvirt URI is: qemu+ssh://matelakat@homes/system
Traceback (most recent call last):
File "/usr/share/virt-manager/virtManager/connection.py", line 940, in _do_open
self._backend.open(cb, data)
~~~~~~~~~~~~~~~~~~^^^^^^^^^^
File "/usr/share/virt-manager/virtinst/connection.py", line 173, in open
conn = libvirt.openAuth(self._open_uri, [valid_auth_options, authcb, cbdata], open_flags)
File "/usr/lib/python3.14/site-packages/libvirt.py", line 147, in openAuth
raise libvirtError('virConnectOpenAuth() failed')
libvirt.libvirtError: Cannot recv data: ssh_askpass: exec(/usr/lib/ssh/ssh-askpass): No such file or directory
Permission denied, please try again.
ssh_askpass: exec(/usr/lib/ssh/ssh-askpass): No such file or directory
Permission denied, please try again.
ssh_askpass: exec(/usr/lib/ssh/ssh-askpass): No such file or directory
matelakat@homes: Permission denied (publickey,password).: Connection reset by peer
The problem was that my key is not on the default location, so ssh was not able to find it and authenticate to the remote system. To avoid the problem, I created a separate entry in ssh config:
host homeshypervisor
User matelakat
ForwardAgent no
HostName homes
IdentityFile <key location here>
IdentitiesOnly yes
The IdentitiesOnly was something I learned today. It will make sure that
for the connection only the explicitely specified identities are used.
Now all I need to do is to set up a dhcp server and confiure nat so I can launch a vm.
One more thing that bothers me is the libvirt daemon's message about
the missing tool, dmidecode
[matelakat@homes ~]$ sudo pacman -S dmidecode
Setup dnsmasq and NAT on the host
First Install DNSMASQ
[matelakat@homes ~]$ sudo pacman -S dnsmasq
Change config, but to do that I need an editor.
[matelakat@homes ~]$ sudo pacman -S vim bash-completion
Adjust configuration file so I have these entries:
bind-interfaces
interface=pubbr
dhcp-range=192.168.115.50,192.168.115.150,12h
Then enable/start it:
[matelakat@homes ~]$ sudo systemctl enable --now dnsmasq.service
Installing the firewall:
[matelakat@homes ~]$ sudo pacman -S firewalld
[matelakat@homes ~]$ sudo systemctl enable --now firewalld.service
Looking at default config:
[matelakat@homes ~]$ sudo firewall-cmd --list-all
public (default, active)
target: default
ingress-priority: 0
egress-priority: 0
icmp-block-inversion: no
interfaces:
sources:
services: dhcpv6-client ssh
ports:
protocols:
forward: yes
masquerade: no
forward-ports:
source-ports:
icmp-blocks:
rich rules:
Adding interface to the public zone, configuring masquerade and dropping non-recognised things:
[matelakat@homes ~]$ sudo firewall-cmd --zone=public --add-interface=wired0 --permanent
success
[matelakat@homes ~]$ sudo firewall-cmd --zone=public --add-masquerade --permanent
success
[matelakat@homes ~]$ sudo firewall-cmd --zone=public --set-target=DROP --permanent
success
[matelakat@homes ~]$ sudo firewall-cmd --reload
success
Adding a new Zone:
[matelakat@homes ~]$ sudo firewall-cmd --permanent --new-zone=pubbr
success
[matelakat@homes ~]$ sudo firewall-cmd --zone=pubbr --add-interface=pubbr --permanent
success
[matelakat@homes ~]$ sudo firewall-cmd --zone=pubbr --add-source=192.168.115.0/24 --permanent
success
[matelakat@homes ~]$ sudo firewall-cmd --zone=pubbr --add-service={dhcp,dns} --permanent
success
[matelakat@homes ~]$ sudo firewall-cmd --zone=pubbr --add-masquerade --permanent
success
[matelakat@homes ~]$ sudo firewall-cmd --reload
success
I am a bit uncertain if I need to add masquerade at both places. I would believe only the public one would need it. But I would need some VM to test it, so launching one.
With the above configuration, I was not able to ping outside servers. So something is definitely missing.
Adding it:
[matelakat@homes ~]$ sudo firewall-cmd --new-policy NAT_pubbr_to_ext --permanent
success
[matelakat@homes ~]$ sudo firewall-cmd --permanent --policy NAT_pubbr_to_ext --add-ingress-zone pubbr
success
[matelakat@homes ~]$ sudo firewall-cmd --permanent --policy NAT_pubbr_to_ext --add-egress-zone public
success
[matelakat@homes ~]$ sudo firewall-cmd --permanent --policy NAT_pubbr_to_ext --set-target ACCEPT
success
[matelakat@homes ~]$ sudo firewall-cmd --reload
success
Adjusting masquerade, removing it from pubbr:
[matelakat@homes ~]$ sudo firewall-cmd --zone=public --query-masquerade
yes
[matelakat@homes ~]$ sudo firewall-cmd --zone=pubbr --query-masquerade
yes
[matelakat@homes ~]$ sudo firewall-cmd --permanent --zone=pubbr --remove-masquerade
success
[matelakat@homes ~]$ sudo firewall-cmd --reload
success
[matelakat@homes ~]$ sudo firewall-cmd --zone=public --query-masquerade
yes
[matelakat@homes ~]$ sudo firewall-cmd --zone=pubbr --query-masquerade
no
Rebooting hypervisor to make sure everything is fine.
Ok, so "script" to set up the firewall are:
firewall-cmd --permanent --zone=public --add-interface=wired0
firewall-cmd --permanent --zone=public --add-masquerade
firewall-cmd --permanent --zone=public --set-target=DROP
firewall-cmd --permanent --new-zone=pubbr
firewall-cmd --permanent --zone=pubbr --add-interface=pubbr
firewall-cmd --permanent --zone=pubbr --add-source=192.168.115.0/24
firewall-cmd --permanent --zone=pubbr --add-service={dhcp,dns}
firewall-cmd --permanent --new-policy NAT_pubbr_to_ext
firewall-cmd --permanent --policy NAT_pubbr_to_ext --add-ingress-zone pubbr
firewall-cmd --permanent --policy NAT_pubbr_to_ext --add-egress-zone public
firewall-cmd --permanent --policy NAT_pubbr_to_ext --set-target ACCEPT
firewall-cmd --reload