Guide: split-Protonmail (offline send/receive qubes + pm bridge vm)


Hello all.

The goal of this guide is to provide you with a split-protonmail setup made of a minimal mail template and three AppVMs: protonmail-bridge, mail-receive, and mail-send.

This will allow you to effectively separate incoming and outgoing mail (into non-networked qubes), and your protonmail credentials (security by compartmentalization).

This guide was inspired by a Reddit post to which I made some modifications, since the configuration proposed in the original post didn’t quite work for me.

I hope this guide can help some of you.

Note 1: I’m not an expert, so I’m sharing what worked for me. If you have suggestions or modification proposals, feel free to post them.
Also, feel free to let me know if I’ve made any mistake so I can update this post accordingly.

Note 2: Protonmail Bridge is currently only available to Protonmail paid accounts.

1. Mail template

Note 1: if you don’t want to create a dedicated template, just make sure that the required software is installed in your template of choice. Personally, I prefer to create a template for each purpose.

Note 2: you can take this a step further by creating a template for Protonmail bridge, and another one for Thunderbird. For simplicity, in this example, I use only one template for both purposes.

Note 3: I’m using a debian-11-minimal template, I haven’t tested this setup with Fedora.

  1. Install the official minimal template as instructed in the Qubes Documentation: Minimal templates | Qubes OS
  2. Clone the minimal template:
[user@dom0]$ qvm-clone debian-11-minimal debian-11-protonmail
  1. Update the new clone:
    Note 1: those of you who set up a apt-cacher-ng qube might need to update the urls of the repositories. Expand the section below for the commands
Howto: Update repo urls to work with `apt-cacher-ng`
[root@debian-11-protonmail]# sed -i 's#https://#http://HTTPS///#g' /etc/apt/sources.list
[root@debian-11-protonmail]# sed -i 's#https://#http://HTTPS///#g' /etc/apt/sources.list.d/*.list
[root@debian-11-protonmail]# apt update && apt full-upgrade -y
  1. Create a packages.txt file, type them or use whatever method you prefer to install the following packages:
[root@debian-11-protonmail]# apt install -y --no-install-recommends $(cat packages.txt)
  1. Download and install Protonmail Bridge, then shutdown the qube:
    Note 1: those of you who set up a apt-cacher-ng qube might need to change the protonmail url from to http://HTTPS///
    Note 2: if you’re using Fedora, you will need to check the Protonmail website for the appropriate package.
[root@debian-11-protonmail]# https_proxy= http_proxy= wget
[root@debian-11-protonmail]# dpkg -i protonmail-bridge_*_amd64.deb && shutdown

2. AppVM: protonmail-bridge

This qube will only run protonmail bridge and will be the only one with a netvm assigned. This example uses sys-whonix, feel free to pick your netvm of choice.

Note 1: Keep in mind that if you pick a different name than protonmail-bridge you will have to adjust some parameters in the following steps.

Note 2: I included a maxmem value that works for me. You can always adjust as needed.

  1. Create the qube:
[user@dom0]$ qvm-create --class=AppVM --template=debian-11-protonmail --label=blue protonmail-bridge
[user@dom0]$ qvm-prefs protonmail-bridge maxmem 900
[user@dom0]$ qvm-prefs protonmail-bridge netvm sys-whonix
  1. Optional: set firewall to Limit outgoing connections to:
  2. Create the policies:
[root@protonmail-bridge]# mkdir -p /rw/usrlocal/etc/qubes-rpc
[root@protonmail-bridge]# echo 'socat STDIO TCP:localhost:1143' > /rw/usrlocal/etc/qubes-rpc/user.protonmail-imap
[root@protonmail-bridge]# echo 'socat STDIO TCP:localhost:1025' > /rw/usrlocal/etc/qubes-rpc/user.protonmail-smtp
  1. Optional: add Protonmail Bridge to appmenu
[user@dom0]$ qvm-features protonmail-bridge menu-items protonmail-bridge.desktop
[user@dom0]$ qvm-sync-appmenus protonmail-bridge
  1. Shutdown the VM:
[user@dom0]$ qvm-shutdown protonmail-bridge

3. AppVM: mail-receive

This qube will only be able to receive mail and will not be connected to a netvm.

  1. Create the qube:
[user@dom0]$ qvm-create --class=AppVM --template=debian-11-protonmail --label=green mail-receive
[user@dom0]$ qvm-prefs protonmail-receive maxmem 900
[user@dom0]$ qvm-prefs protonmail-receive netvm ''
  1. Add the startup command:
[root@mail-receive]# echo 'qvm-connect-tcp ::1143' >> /rw/config/rc.local
  1. Optional: add Thunderbird to appmenu
[user@dom0]$ qvm-features mail-receive menu-items thunderbird.desktop
[user@dom0]$ qvm-sync-appmenus mail-receive
  1. Shutdown the VM:
[user@dom0]$ qvm-shutdown mail-receive

4. AppVM: mail-send

This qube will only be able to send mail and will not be connected to a netvm.

  1. Create the qube:
[user@dom0]$ qvm-create --class=AppVM --template=debian-11-protonmail --label=red mail-send
[user@dom0]$ qvm-prefs protonmail-send maxmem 900
[user@dom0]$ qvm-prefs protonmail-send netvm ''
  1. Add the startup command:
[root@mail-send]# echo 'qvm-connect-tcp ::1025' >> /rw/config/rc.local
  1. Optional: add Thunderbird to appmenu
[user@dom0]$ qvm-features mail-send menu-items thunderbird.desktop
[user@dom0]$ qvm-sync-appmenus mail-send
  1. Shutdown the VM:
[user@dom0]$ qvm-shutdown mail-send

5. dom0 policies

These policies allow communications between the relevant qubes: specifically, the mail-receive qube will be able to fetch email automatically, while the mail-send qube will require an extra user prompt. This set up may or may not be desirable for you, so feel free to experiment.

[root@dom0]# echo "mail-receive protonmail-bridge allow,target=protonmail-bridge" >> /etc/qubes-rpc/policy/user.protonmail-imap
[root@dom0]# echo "mail-send protonmail-bridge ask,default_target=protonmail-bridge" >> /etc/qubes-rpc/policy/user.protonmail-smtp
[root@dom0]# echo "mail-receive @default allow,target=protonmail-bridge" >> /etc/qubes-rpc/policy/qubes.ConnectTCP
[root@dom0]# echo "mail-send @default ask,default_target=protonmail-bridge" >> /etc/qubes-rpc/policy/qubes.ConnectTCP

6. Final configurations

  1. Start protonmail-bridge, login with your Protonmail credentials and make sure that the bridge is set to run on startup (there’s an option in the app settings).
  2. Start mail-receive, add an account on Thunderbird with the credentials provided by Protonmail bridge (NOT your actual Protonmail credentials!). For IMAP use server, port 1143. For SMTP use Connection security: STARTTLS, Normal Password. Then click on Advanced settings to save, and fetch mail.
  3. Start mail-send, add an account on Thunderbird with the credentials provided by Protonmail bridge (NOT your actual Protonmail credentials!). For IMAP use server For SMTP use server, port 1025. Connection security: STARTTLS, Normal Password. Then click Advanced settings to save.
  4. mail-send requires that you approve the Protonmail certificate: you’ll receive a prompt the first time you attempt to send an email.

WaitForSession error?

I’ve fully implemented the protonmail-bridge and mail-receive qubes, but when I try to check mail in Thunderbird nothing happens. journalctl in the mail-receive qube shows the following error:

host qubes.WaitForSession-dom0[2238]: Cannot access user instance remotely.

while all seems good from dom0, which only shows:

dom0 qrexec-policy-daemon[2495]: qrexec: qubes.ConnectTCP+1143: mail-receive → @default: allowed to protonmail-bridge

There was a fix for the WaitForSession error in discussions of the split-browser, but I don’t see how the fix may apply here.

Anyone have ideas on how to proceed?

This error may be due to using whonix templates. Switching to debian-minimal templates alleviated the issue.

Additional notes:

  • Toggle Alternative routing (Settings > Advanced settings) to the Off position to prevent the Proton Mail Bridge from using Google DNS servers, among others. See this Reddit post for more detail.

  • Using the new qrexec policy syntax will futureproof the setup. For example, as an alternative to the third dom0 policy above, I used::

[root@dom0]# echo "qubes.ConnectTCP * mail-receive @default allow target=protonmail-bridge" >> /etc/qubes/policy.d/30-user.policy

I found your guide very helpfull, but why did you decide that spliting recive and send is more secure?

Security by compartmentalization. Say you receive a sensitive document, if you were to use a single vm for sending/receiving, that document could be exfiltrated. With the split setup it has nowhere to go.

1 Like

Can you help me a bit? I done everything like you did step by step but I can’t recive email or send email in mail-receive and mail-send. Is there anything that changed between April and now?

Not that I know of. Did you download the latest version of protonmail bridge?

Also, in dom0 check journalctl -r for related messages. If you have misconfigured policies, you’ll see errors there when you try to send/receive.

I done everything with the up-to-date versions. One thing I did different was using the debian-11 non minimal template, and I have them all with protonmail infront(protonmail-send, protonmail-receive, protonmail-bridge) so it would be a lot easier to remember they are related and I renamed everything in the config files to match.

I’m sure the bridge works as the error is given by qubes(dennied access is what I get in send, but in recive just thunderbird says it can’t connect)

Where exactly do you see this error?

Please check journalctl -r when you try to send/receive and report related messages here.

The receive qube had the wrong port set by mistake, but the send one gets Denied Qubes.ConnectTCP+1025

I’m having the same issue. There seems to be something to do with the following entry in qubes.ConnectTCP:

mail-send @default ask,default_target=protonmail-bridge

journalctl -r shows that the request is being denied because “policy define ‘ask’ action … but no target is available to choose from”.

This is weird, as the syntax seems to be all right, and the default_target is correctly specified.

If I change the mail-send policy to “allow, target=protonmail-bridge”, then it works correctly, but there’s no prompt of course. I’m fine with it, but others may not.

If I keep the “ask” policy and provide no default_target, the prompt also works correctly, but then I have to type/select the protonmail-bridge vm every time.

The issue seems to be related with the default_target parameter, but I’m not sure what can it be, for I have other policies for other services where I use “ask, default_target=…” and everything works as expected.

Any ideas?

another minor issue I discovered… If you move an email from the inbox to a local folder and/or delete the email from the inbox, the email will still persist on the protonmail servers in the all mail folder. So there is no way to remove email from the server using only the bridge, one has to log into webmail and manually remove it from the server.

I wouldn’t call it an issue since that’s how it works by design: the receiving vm doesn’t have internet connectivity.

1 Like

Updating bridge to v. 3.0.x

Proton is now hosting the bridge download under their new url, which causes an error when downloading via proxy. For step 5 of 1. Mail template above, with the latest update one should now use the following (edit for current version, 3.0.21-1 as of this post):

[root@debian-11-protonmail]# https_proxy= http_proxy= wget
[root@debian-11-protonmail]# dpkg -i protonmail-bridge_*_amd64.deb && shutdown

Version 3.0.x of the bridge also requires an additional package:

apt-get install libopengl0

After updating, Thunderbird will hang with the message “Checking mail server capabilities”. To fix this, copy the IMAP password from the Mailbox details section of the protonmail bridge app and reset the certificate as follows: (source: reddit)

From Thunderbird, to remove the certificates, go to Menu → Settings → Privacy & Security → Manage Certificates at the bottom. From here, on the “Servers” tab, remove the entries for, and then restart Thunderbird, and click “Get Messages”. You should be prompted to approve the new certificates.

1 Like