If you've ever wanted others to securely discover your OpenPGP public key without sending them a file or relying on public key servers, Web Key Directory (WKD) is one of the easiest ways to accomplish it.
WKD allows supported OpenPGP clients, including GnuPG, to automatically retrieve your public key directly from your domain. Instead of telling someone to download your key manually or search a public key server, their email client can locate the correct key automatically when they attempt to send you an encrypted email.
Since I already host my own infrastructure behind Nginx, adding WKD support only required a small amount of configuration. In this article, I'll explain what WKD is, why it's useful, how it works, and walk through the basic configuration needed to publish your own public key.
What is WKD?
Web Key Directory is an OpenPGP standard that allows domains to publish users' public encryption keys in a predictable location. Instead of depending on third-party key servers, the domain owner hosts the key directly.
When someone runs a command such as:
gpg --locate-keys [email protected]
GnuPG calculates a hash from the email address and automatically requests the corresponding key from the domain's WKD endpoint. If everything is configured correctly, the key is imported without the user needing to know anything about where it is stored.
How WKD Works
+-----------------------+
| gpg --locate-keys |
| [email protected] |
+-----------+-----------+
|
|
▼
https://dwroten.com
|
▼
/.well-known/openpgpkey/hu/
|
▼
Hashed User ID
|
▼
Public Key Downloaded
Why Use WKD?
Before WKD became widely supported, the most common ways of sharing OpenPGP keys were:
- Uploading them to public key servers
- Hosting them somewhere on your website
- Emailing them as attachments
While these methods still work, each has drawbacks. Public key servers can contain outdated or duplicate keys, manually downloading files isn't particularly user friendly, and emailing public keys requires additional effort for both parties.
WKD solves many of these problems by letting your own domain become the authoritative source for your public key.
| Method | Automatic Discovery | Hosted by You | Recommended |
|---|---|---|---|
| WKD | |||
| Public Key Servers | |||
| Website Download | |||
| Email Attachment |
Prerequisites
Before setting up WKD, you'll need a few things already in place:
- A domain name that you control
- An existing OpenPGP key pair
- GnuPG installed
- A web server such as Nginx
- A valid HTTPS certificate
If you don't already have an OpenPGP key pair, you can generate one using:
root@nginx:~# gpg --full-generate-key
Once your key has been generated, verify it exists:
root@nginx:~# gpg --list-secret-keys --keyid-format LONG
Generating the WKD Hash
This is usually the step that confuses people the most. The filename used by WKD is not your email address and is not the name of the exported key file. Instead, it is a hash generated from the local part of your email address and encoded using z-base-32.
For example, email address:
[email protected]
WKD uses:
contact
to generate the hashed filename.
The easiest way to generate the required filename is using the WKD helper tools included with GnuPG:
root@nginx:~# gpg-wks-client --print-wkd-url [email protected]
This will output the WKD location where your public key should be published.
https://dwroten.com/.well-known/openpgpkey/hu/<hashed-user-id>
The final file should be placed at that location with no file extension.
For example:
.well-known/
└── openpgpkey/
└── hu/
└── dj3498u4hyyarh35rkjfnghbjxug6b19
The exported public key from the previous step should be renamed to this hashed filename:
root@nginx:~# gpg --export --output publickey.gpg [email protected]
root@nginx:~# mv publickey.gpg dj3498u4hyyarh35rkjfnghbjxug6b19
.gpg or .asc. The filename itself is the
generated hash.
Configuring Nginx
Once your files have been generated, we can move onto actually hosting the key. Depending on your set up, you could create the directories and place your public key into your public directory of your site. Since I'm already running Nginx I opted to just host the keys there.
You can create the directory using the following mkdir command:
root@nginx:~# mkdir -p /var/www/html/.well-known/openpgpkey/hu/
The policy file is part of the WKD specification. While it can contain policy information for advanced deployments, an
empty file is sufficient for most personal websites.
root@nginx:~# touch /var/www/html/.well-known/openpgpkey/hu/policy
Now that we have the structure created, we can move our key to the proper directory:
root@nginx:~# mv dj3498u4hyyarh35rkjfnghbjxug6b19 /var/www/html/.well-known/openpgpkey/hu/
Once the directory has been created and our key copied, we can finally add the Nginx configuration to the vhost:
location /.well-known/openpgpkey {
default_type "application/octet-stream";
add_header Access-Control-Allow-Origin * always;
alias /var/www/html/.well-known/openpgpkey;
}
Make sure to test and apply the changes:
root@nginx:~# nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
root@nginx:~# service nginx reload
Your configuration may differ depending on how your virtual hosts are organized, but the important part is ensuring the WKD files are accessible over HTTPS.
Testing Your Configuration
Once everything is in place, the easiest way to verify your setup is by asking GnuPG to locate your key:
root@vm:~# gpg --locate-keys [email protected]
gpg: key AE657ED83F042F31: public key "David Wroten <[email protected]>" imported
gpg: Total number processed: 1
gpg: imported: 1
pub ed25519 2024-08-08 [SC] [expires: 2029-02-10]
CAFAF6EC10D5CE722C3BCA41AE657ED83F042F31
uid [ unknown] David Wroten <[email protected]>
sub cv25519 2024-08-08 [E] [expires: 2027-08-08]
sub cv25519 2026-02-11 [E] [expires: 2029-02-10]
If everything has been configured correctly, GnuPG should download and import your public key automatically.
unknown trust level is expected when importing a key for the first time. It simply means the key
has not yet been marked as trusted in your local keyring.
You can also verify that the files are reachable using curl:
root@vm:~# curl -I https://dwroten.com/.well-known/openpgpkey/hu/dj3498u4hyyarh35rkjfnghbjxug6b19
Troubleshooting
404 Errors
Double-check your directory structure, filename hash, and Nginx configuration.
Permission Problems
Verify the web server has read access to the WKD files and directories.
HTTPS Issues
WKD requires HTTPS. Make sure your certificates are valid and redirects are functioning correctly.
Incorrect Hash
One of the most common mistakes is manually naming the file instead of allowing the helper tools to generate the proper hash.
Final Thoughts
WKD is one of those technologies that quietly improves the OpenPGP experience without requiring much ongoing maintenance. Once configured, your domain becomes the authoritative source for your public key, making encrypted communication easier for anyone using compatible email clients or GnuPG. If you're already hosting your own infrastructure with Nginx, it's a worthwhile addition that only takes a few minutes to implement.