Table of Contents
The up and coming split-gpg2 feature is pretty cool. Unfortunately there are a lot of people around the internet who are not sure how to set it up, or are telling others wrong info
Basically for split-gpg2 you only need to install split-gpg2-dom0
and split-gpg2
in all the relevant domains; set a few features on some qubes; and set up a valid gpg key. Then it seems most gnupg commands will just werk
For Sequoia and its chameleon project, since it doesn't implement everything that gnupg does, you have to import your keys using gnupg (i.e. /bin/gpg
). Once you do, gpg-sq
will use them and split-gpg2 will work with all the above
Setting up
For the sake of example, I'll use the following variables:
EXAMPLE_SERVER_TEMPLATE=
EXAMPLE_SERVER_APPVM=
EXAMPLE_CLIENT_TEMPLATE=
EXAMPLE_CLIENT_APPVM=
EXAMPLE_PGP_UID=
If you fill them out in your terminal, you should be able to copy and paste most commands here
dom0
Install
split-gpg2-dom0
Add the following file somewhere in
/etc/qubes/policy.d
:qubes.Gpg2 + @tag:split-gpg2-client @tag:split-gpg2-server allow notify=yes qubes.Gpg2 + @tag:dev-vm @tag:split-gpg2-server allow notify=yes qubes.Gpg2 + @tag:split-gpg2-client @default ask target=vault-pgp qubes.Gpg2 + @anyvm @tag:split-gpg2-server ask default_target=vault-pgp
This will let us set up which VMs can ask/respond to GPG requests by using tags
Create the server domains:
# make the template from fedora-41-xfce (you can choose whatever you like) qvm-create \ --label=black \ --class=TemplateVM \ --memory=400 \ --maxmem=800 \ --vcpus=2 \ --template=fedora-41-xfce \ "${EXAMPLE_SERVER_TEMPLATE}" # make the appvm qvm-create \ --label=gray \ --class=AppVM \ --memory=400 \ --maxmem=800 \ --vcpus=2 \ --netvm="" \ --templates="${EXAMPLE_SERVER_TEMPLATE}" \ "${EXAMPLE_SERVER_APPVM}" # give it the tag we need for the rpc policies qvm-tags "${EXAMPLE_SERVER_APPVM}" add split-gpg2-server
Create the client domains:
# make the template from fedora-41-xfce etc qvm-create \ --label=black \ --class=TemplateVM \ --memory=400 \ --maxmem=800 \ --vcpus=2 \ --template=fedora-41-xfce \ "${EXAMPLE_CLIENT_TEMPLATE}" # make the appvm from that qvm-create \ --label=gray \ --class=AppVM \ --memory=400 \ --maxmem=800 \ --vcpus=2 \ --templates="${EXAMPLE_CLIENT_TEMPLATE}" \ "${EXAMPLE_CLIENT_APPVM}" # this is how we trigger the split-gpg2 service from qubes qvm-features "${EXAMPLE_CLIENT_APPVM}" enable "service.split-gpg2-client" # and tag it for the policies qvm-tags "${EXAMPLE_CLIENT_APPVM}" add split-gpg2-client
In the guests
In both templates:
- Ensure
split-gpg2
,sequoia-sq
, andsequoia-chameleon-gnupg
are installed
Preparing the server
In the server, we'll generate a valid key and import it for use with split-gpg2
In the $EXAMPLE_SERVER_APPVM, run the following:
# Generate a key with sq and output it to example.pgp
sq key generate \
--userid "${EXAMPLE_PGP_UID}" \
--own-key \
--without-password \
--output example.pgp \
--rev-cert example.rev
# Generate a public key (a certificate)
sq key delete \
--cert-file=example.pgp \
--output=example.cert
# Import them into gnupg
/bin/gpg --import example.pgp
/bin/gpg --no-tty --command-fd 0 --edit-key "${EXAMPLE_PGP_UID}" <EOF
trust
5
quit
EOF
# Export the ownertrust
/bin/gpg -a --export-ownertrust > example-trust.asc
# Send them to ${EXAMPLE_CLIENT_APPVM}
qvm-copy example-trust.asc example.cert
Preparing the client
The clients' side is straightfowrard:
# import the certificates you just copied
/bin/gpg --import "~/QubesIncoming/${EXAMPLE_SERVER_APPVM}/example.cert"
/bin/gpg --import-ownertrust "~/QubesIncoming/${EXAMPLE_SERVER_APPVM}/example-trust.asc"
sq cert import "~/QubesIncoming/${EXAMPLE_SERVER_APPVM}/example.cert"
# set up some user session-wide environment variables
# so that `split-gpg2-client.service` knows where to target
mkdir -p "${HOME}/.config/environment.d"
cat <<-EOF > "${HOME}/.config/environment.d/qubes-split-gpg2.conf"
SPLIT_GPG2_SERVER_DOMAIN=${EXAMPLE_SERVER_APPVM}
EOF
And now you can try it out!
As long as the keys are imported in the gnupg keystore and picked up by the gpg-agent, and your policies are well written, then it should work:
# gnupg
/bin/gpg -k
/bin/gpg -K
# sequoia-chameleon-gnupg
gpg-sq -k
gpg-sq -K
# sequoia-sq
sq cert list
sq key list
Every second of the above calls (the ones querying secret keys) should trigger a prompt or a notification alerting you about a qubes.Gpg2
call
Configuring Software
split-gpg2 doesn't need any configuration on the softwares' side; but you can opt into using sequoia over gnupg!
Thunderbird
Thunderbird simply needs the same settings as the old split gpg, but instead of the client wrapper, but gpg-sq
git
For git, likewise, set this in your ~/.gitconfig
:
[gpg]
program = gpg-sq
# ...
Going deeper
There are still some things I haven't played with yet. Namely:
By default, the
splitgpg2
service on server side tries to export the secret subkeys to make secondary keyrings. This means I can't use it with my Onlykey, since they private key material can't be extracted from it. Incidentally, it's also where thegpg-sq
drop-in failsBut in the comments of the example config, I found this:
# 'source_keyring_dir' option - use a different source keyring. If not set, # the default is to use the home directory computed above. Secret subkeys (but # *not* the main key!) will be imported from this directory to the directory # 'qubes-auto-keyring' under the home directory. Set this to 'no' to # disable the feature and give clients access to all secret keys. This # is not recommended as it allows clients to sign other OpenPGP keys.
Reading this, I'm hoping that if
source_keyring_dir
is set tono
, it won't bother extract the subkeys at all, and maybe the rest of the commands will just werkI wonder if I can get
splitgpg2
to work withsq
directly, or at least its keystore