Some time ago, I posted a workaround for running OpenSnitch across multiple VMs called Split-OpenSnitch with Per-VM Identity.

There is now a much better way to solve this natively! I have submitted a PR to the upstream OpenSnitch project that solves the node identity problem by using node_id as the canonical remote node identity. The PR is still pending, but I have successfully tested it on a Fedora 43 VM running the UI alongside 4 daemon nodes.

For anyone who wants to test this out on Qubes OS with Fedora templates, here is a complete guide to patching OpenSnitch v1.8.0 and building the RPM packages locally.

1. Install Build Dependencies

First, you need to install the system build tools and libraries:

sudo dnf install -y \
  git rpm-build rpmdevtools \
  golang protobuf-compiler golang-google-protobuf protoc-gen-go-grpc \
  clang llvm make gcc \
  libnetfilter_queue-devel libpcap-devel \
  python3-devel python3-setuptools python3-pip python3-packaging \
  qt5-linguist

For runtime and testing after installation, these packages are also highly recommended:

sudo dnf install -y \
  python3-pyqt6 python3-protobuf python3-grpcio \
  python3-inotify python3-slugify python3-grpcio python3-grpcio-tools

2. Save the Fedora Build Fixes Patch

To successfully package v1.8.0 on Fedora, you will need a few minor build tweaks. Expand the section below, copy the patch text, and save it as 0002-v1.8.0-local-fedora-rpm-build-fixes.patch in your working directory.

[details="Fedora Build Fixes Patch (0002-v1.8.0-local-fedora-rpm-build-fixes.patch)"]

From 6f756561842d4e090e8e9e51d2c6766d95dd904f Mon Sep 17 00:00:00 2001
From: nyymi <a01@truewall.eu>
Date: Fri, 3 Apr 2026 08:12:45 +0300
Subject: [PATCH] build: local Fedora RPM packaging fixes for v1.8.0

---
 ebpf_prog/Makefile                         |  3 ++-
 ui/i18n/generate_i18n.sh                   |  5 ++++-
 utils/packaging/daemon/rpm/opensnitch.spec | 13 ++++++-------
 utils/packaging/ui/rpm/opensnitch-ui.spec  |  8 ++++----
 4 files changed, 16 insertions(+), 13 deletions(-)

diff --git a/ebpf_prog/Makefile b/ebpf_prog/Makefile
index 558508fe..747cc74c 100644
--- a/ebpf_prog/Makefile
+++ b/ebpf_prog/Makefile
@@ -58,13 +58,14 @@ CFLAGS = -I. \
    -Wno-address-of-packed-member \
    -Wno-tautological-compare \
    -Wno-unknown-warning-option  \
+   -fms-extensions \
    -fno-stack-protector \
    -g -O2 -emit-llvm

 all: $(BIN)

 %.bc: %.c
-   $(CC) $(CFLAGS) -c $<
+   $(CC) $(CFLAGS) -c $< -o $@

 %.o: %.bc
    $(LLC) -march=bpf -mcpu=generic -filetype=obj -o $@ $<
diff --git a/ui/i18n/generate_i18n.sh b/ui/i18n/generate_i18n.sh
index 55622ea9..1babffc5 100755
--- a/ui/i18n/generate_i18n.sh
+++ b/ui/i18n/generate_i18n.sh
@@ -3,7 +3,10 @@
 app_name="opensnitch"
 langs_dir="./locales"
 lrelease_bin=""
-for lbin in $LRELEASE lrelease lrelease6 lrelease-qt6
+# On some distros the Qt linguist tools live under qt5/qt6 libexec paths,
+# but are not added to the user PATH.
+PATH=$PATH:/usr/lib/qt6/bin:/usr/lib64/qt6/bin:/usr/lib64/qt5/bin/
+for lbin in $LRELEASE lrelease lrelease6 lrelease-qt6 lrelease-qt5
 do
     lrelease_bin="$(command -v $lbin)"
     if [ -n "$lrelease_bin" ]; then
diff --git a/utils/packaging/daemon/rpm/opensnitch.spec b/utils/packaging/daemon/rpm/opensnitch.spec
index ecccfa51..01af46b0 100644
--- a/utils/packaging/daemon/rpm/opensnitch.spec
+++ b/utils/packaging/daemon/rpm/opensnitch.spec
@@ -1,6 +1,6 @@
 Name:           opensnitch
 Version:        1.8.0
-Release:        1%{?dist}
+Release:        1.qubes1%{?dist}
 Summary:        OpenSnitch is a GNU/Linux interactive application firewall

 License:        GPLv3+
@@ -31,12 +31,11 @@ rm -rf %{buildroot}
 %setup

 %build
-mkdir -p go/src/github.com/evilsocket
-ln -s $(pwd) go/src/github.com/evilsocket/opensnitch
-export GOPATH=$(pwd)/go
-cd go/src/github.com/evilsocket/opensnitch/
-make protocol
-cd go/src/github.com/evilsocket/opensnitch/daemon/
+mkdir -p daemon/ui/protocol
+protoc -Iproto proto/ui.proto --go_out=daemon/ui/protocol --go-grpc_out=daemon/ui/protocol --go_opt=paths=source_relative --go-grpc_opt=paths=source_relative
+perl -0pi -e 's/SupportPackageIsVersion8/SupportPackageIsVersion7/g; s/cOpts := append\(\[\]grpc\.CallOption\{grpc\.StaticMethod\(\)\}, opts\.\.\.\)/cOpts := opts/g' daemon/ui/protocol/ui_grpc.pb.go
+make -C ebpf_prog KERNEL_VER="$(uname -r)"
+cd daemon/
 go mod vendor
 go build -o opensnitchd .

diff --git a/utils/packaging/ui/rpm/opensnitch-ui.spec b/utils/packaging/ui/rpm/opensnitch-ui.spec
index be325807..f73b7a8c 100644
--- a/utils/packaging/ui/rpm/opensnitch-ui.spec
+++ b/utils/packaging/ui/rpm/opensnitch-ui.spec
@@ -1,8 +1,7 @@
 %define name opensnitch-ui
 %define version 1.8.0
 %define unmangled_version 1.8.0
-%define release 1
-%define __python python3
+%define release 1.qubes1
 %define desktop_file opensnitch_ui.desktop

 Summary: Prompt service and UI for the OpenSnitch interactive application firewall.
@@ -75,13 +74,14 @@ fi


 %build
+export PATH=/usr/lib64/qt5/bin:/usr/lib64/qt6/bin:/usr/lib/qt6/bin:$PATH
 cd i18n; make; cd ..
 pyrcc5 -o opensnitch/resources_rc.py opensnitch/res/resources.qrc
 find opensnitch/proto/ -name 'ui_pb2_grpc.py' -exec sed -i 's/^import ui_pb2/from . import ui_pb2/' {} \;
-python3 setup.py build
+/usr/bin/python3 setup.py build

 %install
-python3 setup.py install --install-lib=/usr/lib/python3/dist-packages/ --single-version-externally-managed -O1 --root=$RPM_BUILD_ROOT --prefix=/usr --record=INSTALLED_FILES --install-scripts=/usr/bin
+/usr/bin/python3 setup.py install --install-lib=/usr/lib/python3/dist-packages/ --single-version-externally-managed -O1 --root=$RPM_BUILD_ROOT --prefix=/usr --record=INSTALLED_FILES --install-scripts=/usr/bin

 %clean
 rm -rf $RPM_BUILD_ROOT
-- 
2.53.0
[/details]

3. Clone and Patch the Repository

We'll clone the official v1.8.0 repository, pull the main fix directly from GitHub PR #1578, and apply our local Fedora build patch.

# Clone the repository
git clone https://github.com/evilsocket/opensnitch.git
cd opensnitch

# Switch to the v1.8.0 branch
git checkout v1.8.0

# Download and apply PR #1578

curl -L -O https://github.com/evilsocket/opensnitch/pull/1578.patch
git am 1578.patch


# apply the Fedora fix
git am ../0002-v1.8.0-local-fedora-rpm-build-fixes.patch

4. Setup the Build Directory and Archive Sources

Set up the standard RPM build directories, then package up the patched source code.

# Create RPM directories
mkdir -p ~/rpmbuild/{BUILD,BUILDROOT,RPMS,SOURCES,SPECS,SRPMS}

# Archive the daemon source
git archive \
  --format=tar.gz \
  --prefix=opensnitch-1.8.0/ \
  HEAD \
  > ~/rpmbuild/SOURCES/opensnitch_1.8.0.orig.tar.gz

# Archive the UI source
git archive \
  --format=tar.gz \
  --prefix=opensnitch-ui-1.8.0/ \
  HEAD:ui \
  > ~/rpmbuild/SOURCES/opensnitch-ui-1.8.0.tar.gz

# Copy the patched spec files
cp utils/packaging/daemon/rpm/opensnitch.spec ~/rpmbuild/SPECS/
cp utils/packaging/ui/rpm/opensnitch-ui.spec ~/rpmbuild/SPECS/

5. Build the RPMs

Now, build your RPMs. (Remember to activate your micromamba environment here if that is where pyrcc5 lives).

# Build the daemon RPM
rpmbuild -ba --define "_topdir $HOME/rpmbuild" ~/rpmbuild/SPECS/opensnitch.spec

# Build the UI RPM
rpmbuild -ba --define "_topdir $HOME/rpmbuild" ~/rpmbuild/SPECS/opensnitch-ui.spec

Once finished, your compiled RPMs will be waiting in ~/rpmbuild/RPMS/. Install them in your respective templates/AppVMs, configure your nodes, and you're good to go!