// step 01
Export your public key as binary.
WKD serves OpenPGP binary, not ASCII armored. From PGPony, get the public key out via the
Exchange tab → Show My Key → Share
(gives you the ASCII-armored block; convert to binary on the desktop). Or use a desktop gpg
copy if you already have one:
If PGPony only outputs ASCII armored, convert on the desktop:
gpg --import your-public-key.asc
gpg --export YOUR_FINGERPRINT > pubkey.gpg
The resulting pubkey.gpg is what goes on the web server.
// step 02
Compute the WKD hash.
Run on desktop gpg:
gpg --with-wkd-hash --list-keys you@yourdomain.com
Look for the line below your User ID:
uid [ultimate] You <you@yourdomain.com>
7we1qpoqxxh1ie3wxxxxxxxxxxxxxxxx@yourdomain.com
The hash on the left of @ is the localpart-hash you need. Z-base-32 encoded SHA-1
of the lowercased localpart. This is your filename on the server.
// step 03
Decide on Direct or Advanced method.
Direct method: WKD lives on your main domain.
URL pattern: https://yourdomain.com/.well-known/openpgpkey/hu/HASH
Advanced method: WKD lives on a dedicated subdomain.
URL pattern: https://openpgpkey.yourdomain.com/.well-known/openpgpkey/yourdomain.com/hu/HASH
Clients try Advanced first, fall back to Direct. Setting up both is most robust; Direct alone
is simpler and usually sufficient.
// step 04
Create the directory structure.
On your web server (using Direct method, document root /var/www/yourdomain.com):
mkdir -p /var/www/yourdomain.com/.well-known/openpgpkey/hu
cd /var/www/yourdomain.com/.well-known/openpgpkey
// step 05
Place the public key binary.
Copy your pubkey.gpg into the hu/ directory, renaming it to the
hash from Step 2 — no file extension:
cp pubkey.gpg /var/www/yourdomain.com/.well-known/openpgpkey/hu/7we1qpoqxxh1ie3wxxxxxxxxxxxxxxxx
// step 06
Add the policy file.
Create an empty policy file at .well-known/openpgpkey/policy. Its existence
signals WKD support; its content is not used (in practice):
touch /var/www/yourdomain.com/.well-known/openpgpkey/policy
// step 07
Configure web server headers.
The WKD endpoint should serve with Content-Type: application/octet-stream and
permissive CORS (so JavaScript-based clients can fetch). Nginx example:
location /.well-known/openpgpkey/ {
default_type application/octet-stream;
add_header Access-Control-Allow-Origin "*";
add_header Cache-Control "public, max-age=3600";
}
Reload Nginx: sudo nginx -s reload.
// step 08
Test from a desktop.
Confirm WKD returns your key:
gpg --auto-key-locate=clear,wkd --locate-keys you@yourdomain.com
Successful WKD discovery prints your key. Failure prints a "no public key" error or fetch
failure — recheck the hash, file path, and Content-Type header.