How stable is Mirage Firewall in daily use?
I found two “guides.” Has anyone used one of them?
https://gist.github.com/100111001/4eca0f78ed69d597d562a1515168fa6c
# How to install the superlight mirage-firewall for Qubes OS by using saltstack
# Tested on Qubes v4.2 and mirage v0.9.5
# No integrity checks are performed. Latest release version of mirage is downloaded and installed into dom0
# After the install, you have to switch your AppVMs to use the mirage firewall vm created by this script
# inspired by: https://github.com/one7two99/my-qubes/tree/master/mirage-firewall
# inspired by: https://github.com/one7two99/my-qubes/tree/master/mirage-firewall
# default template + dispvm template are used. Possible optimization is to use min-dvms
{% set DownloadVMTemplate = salt['cmd.shell']("qubes-prefs default_template") %}
{% set DispVM = salt['cmd.shell']("qubes-prefs default_dispvm") %}
{% set DownloadVM = "DownloadVmMirage" %}
{% set MirageFW = "sys-mirage-fw" %}
{% set GithubUrl = "https://github.com/mirage/qubes-mirage-firewall" %}
{% set Filename = "qubes-firewall.xen" %}
{% set MirageInstallDir = "/var/lib/qubes/vm-kernels/mirage-firewall" %}
#download and install fixed version
{# % set Release = "v0.8.4" % #}
#or latest version
#command to get the latest version: Release=`curl --silent --location -o /dev/null -w %{url_effective} $GithubUrl/releases/latest | rev | cut -d "/" -f 1 | rev`
{% set Release = salt['cmd.shell']("qvm-run --dispvm " ~ DispVM ~ " --pass-io \"curl --silent --location -o /dev/null -w %{url_effective} " ~ GithubUrl ~ "/releases/latest | rev | cut -d \"/\" -f 1 | rev\"") %}
{# % set sha2FromLastBuild = salt['cmd.shell']("qvm-run --pass-io --dispvm " ~ DispVM ~ " \"curl -s https://raw.githubusercontent.com/mirage/qubes-mirage-firewall/refs/heads/main/qubes-firewall-release.sha256 | cut -d\' \' -f1 \" ") % #}
{% if Release != salt['cmd.shell']("[ ! -f " ~ MirageInstallDir ~ "/version.txt" ~ " ] && touch " ~ MirageInstallDir ~ "/version.txt" ~ ";cat " ~ MirageInstallDir ~ "/version.txt") %}
create-downloader-VM:
qvm.vm:
- name: {{ DownloadVM }}
- present:
- template: {{ DownloadVMTemplate }}
- label: red
- prefs:
- template: {{ DownloadVMTemplate }}
- include-in-backups: false
{% set DownloadBinary = GithubUrl ~ "/releases/download/" ~ Release ~ "/" ~ Filename %}
download-and-unpack-in-DownloadVM4mirage:
cmd.run:
- names:
- qvm-run --pass-io {{ DownloadVM }} {{ "curl -L -O " ~ DownloadBinary }}
- require:
- create-downloader-VM
check-checksum-in-DownloadVM:
cmd.run:
- names:
- qvm-run --pass-io {{ DownloadVM }} {{ "\"echo \\\"Checksum of last build on github:\\\";curl -s https://raw.githubusercontent.com/mirage/qubes-mirage-firewall/refs/heads/main/qubes-firewall-release.sha256 | cut -d\' \' -f1 \"" }}
- qvm-run --pass-io {{ DownloadVM }} {{ "\"echo \\\"Checksum of downloaded local file:\\\";sha256sum ~/" ~ Filename ~ " | cut -d\' \' -f1\"" }}
- qvm-run --pass-io {{ DownloadVM }} {{ "\"diff <(curl -s https://raw.githubusercontent.com/mirage/qubes-mirage-firewall/refs/heads/main/qubes-firewall-release.sha256 | cut -d\' \' -f1 ) <(sha256sum ~/" ~ Filename ~ " | cut -d\' \' -f1) && echo \\\"Checksums DO match.\\\" || (echo \\\"Checksums do NOT match.\\\";exit 101)\"" }} #~/mirage-firewall/modules.img
- require:
- download-and-unpack-in-DownloadVM4mirage
copy-mirage-kernel-to-dom0:
cmd.run:
- name: mkdir -p {{ MirageInstallDir }}; qvm-run --pass-io --no-gui {{ DownloadVM }} " {{ "cat ~/" ~ Filename }} " > {{ MirageInstallDir ~ "/vmlinuz" }}
- require:
- download-and-unpack-in-DownloadVM4mirage
- check-checksum-in-DownloadVM
create-initramfs:
cmd.run:
- names:
- gzip -n9 < /dev/null > {{ MirageInstallDir ~ "/initramfs" }}
- echo {{ Release }} > {{ MirageInstallDir ~ "/version.txt" }}
- require:
- copy-mirage-kernel-to-dom0
create-sys-mirage-fw:
qvm.vm:
- name: {{ MirageFW }}
- present:
- class: StandaloneVM
- label: black
- prefs:
- kernel: mirage-firewall
- kernelopts:
- include-in-backups: False
- memory: 32
- maxmem: 32
- netvm: sys-net
- provides-network: True
- vcpus: 1
- virt-mode: pvh
- features:
- enable:
- qubes-firewall
- no-default-kernelopts
- require:
- copy-mirage-kernel-to-dom0
cleanup-in-DownloadVM:
cmd.run:
- names:
- qvm-run -a --pass-io --no-gui {{ DownloadVM }} "{{ "rm " ~ Filename ~ "; rm -R ~/mirage-firewall" }}"
- require:
- create-initramfs
remove-DownloadVM4mirage:
qvm.absent:
- name: {{ DownloadVM }}
- require:
- cleanup-in-DownloadVM
{% endif %}
https://privsec.dev/posts/qubes/firewalling-with-mirageos-on-qubes-os/
Installing the unikernel
To deploy MirageOS, you need to copy the vmlinuz and initramfs files from their releases page to /var/lib/qubes/vm-kernels/mirage-firewall in dom0.
TemplateVM
Create a TemplateVM:
qvm-create \
--property kernel=mirage-firewall \
--property kernelopts='' \
--property memory=64 \
--property maxmem=64 \
--property vcpus=1 \
--property virt_mode=pvh \
--label=black \
--class TemplateVM \
your_template_name
Don’t worry if the TemplateVM doesn’t launch — we don’t need it to.
Disposable Template
Next, create a disposable template based on the TemplateVM you have just created.
qvm-create \
--property template=your_template_name \
--property provides_network=True \
--property template_for_dispvms=True \
--label=orange \
--class AppVM \
your_disposable_template_name
qvm-features your_disposable_template_name qubes-firewall 1
qvm-features your_disposable_template_name no-default-kernelopts 1
Your disposable templates should now launch and shut down properly.
Disposable FirewallVMs
You can now create disposable FirewallVMs based on your disposable template. I recommend replacing sys-firewall with a disposable Mirage firewall. If you use ProxyVMs like sys-whonix, I recommend that you add a disposable Mirage Firewall after the ProxyVM as well, and use it as the net qube for your AppVMs.
qvm-create \
--property template=your_disposable_template_name \
--property provides_network=True \
--property netvm=your_net_qube_name \
--label=orange \
--class DispVM \
your_firwall_name
Or what other instructions did you use?