I host my gpg key on my personal nginx server, and make it accessible via https (gpg.mxmeinhold.com) and WKD. This means my key is obtainable by curl or by auto-key-locate, e.g.:
$ curl -L gpg.mxmeinhold.com | gpg --import-options show-only --import
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 178 100 178 0 0 2918 0 --:--:-- --:--:-- --:--:-- 2966
100 11406 100 11406 0 0 64440 0 --:--:-- --:--:-- --:--:-- 64440
pub rsa4096 2018-03-05 [SC] [expires: 2023-01-23]
B77D730E8D444707FA93320D72E05836F8252405
uid Max Meinhold <[email protected]>
uid Max Meinhold <[email protected]>
uid Max Meinhold <[email protected]>
sub rsa4096 2018-03-05 [E] [expires: 2022-02-17]
sub rsa4096 2018-11-30 [S] [expires: 2022-02-17]
sub rsa4096 2020-09-27 [A] [expires: 2022-02-17]
$ gpg --auto-key-locate clear,wkd,local --locate-keys [email protected]
gpg: key 72E05836F8252405: "Max Meinhold <[email protected]>" not changed
gpg: Total number processed: 1
gpg: unchanged: 1
pub rsa4096 2018-03-05 [SC] [expires: 2023-01-23]
B77D730E8D444707FA93320D72E05836F8252405
uid [ultimate] Max Meinhold <[email protected]>
uid [ultimate] Max Meinhold <[email protected]>
uid [ultimate] Max Meinhold <[email protected]>
sub rsa4096 2018-03-05 [E] [expires: 2022-02-17]
sub rsa4096 2018-11-30 [S] [expires: 2022-02-17]
sub rsa4096 2020-09-27 [A] [expires: 2022-02-17]
Having the https link is quite useful for me, since I can pull my pub key via curl or give the short link to others, without having to rely on the keyservers, since I self host it.
This parts pretty simple. I've run gpg --armor --export $KEYID > /var/www/gpg.example.com/pubkey.gpg
, and configured nginx to serve the file by default as text/plain. I've attached my config to this gist as gpg.example.com.conf
. I'm using certbot for ssl certs.
WKD actually looks for a given key in 2 different places. If you're searching for [email protected]
's key, it will check example.com/.well-known/openpgpkey/hu/<WKD_HASH>
and openpgpkey.example.com/.well-known/openpgpkey/example.com/hu/<WKD_HASH>
. I'm serving both out of the same directory, so the structure I have is as follows:
.well-known/
openpgpkey/
policy
hu/
<WKD_HASH>
example.com/
policy
hu/
<WKD_HASH>
You need the policy files, though they can just be empty files. I have both them and the <WKD_HASH>
set as executable, since I was running into permissions issues when I first put this together.
I deploy and update those files from my keyring with the script update-gpg.sh
, and serve them with example.com.conf
. Note that you'll need the allow origin header in the nginx config.
For testing this, using gpg alone can be a little tricky, because dirmngr will cache failures, and it doesn't have the most verbose reporting. You can use a tester like this one to see if your config is working.
Thank you for great examples!