Applies to: GnuPG 2.4 (tested with 2.4.7 on Debian 13; Ubuntu 26.04 ships 2.4.8 and Ubuntu 24.04 2.4.4)
GnuPG (the gpg command) encrypts and signs files with OpenPGP keys. The basic workflow: create a key pair with gpg --full-generate-key, give your public key to others with gpg --armor --export, encrypt for someone with gpg --encrypt --recipient, decrypt with gpg --decrypt, and check signatures with gpg --verify. On a server it is handy for encrypting backups before they leave the machine and for checking that downloads are genuine.
Install
Minimal Debian and Ubuntu images, such as the official Docker images we tested, only have gpgv (verify only). Install the full tool:
sudo apt install gnupg # Debian, Ubuntu gpg --version
AlmaLinux 9 already has it (package gnupg2, version 2.3.3).
1. Create a key pair
gpg --full-generate-key
GnuPG 2.4 asks, in this order:
- Kind of key: accept
(9) ECC (sign and encrypt) *default*, then(1) Curve 25519 *default*. - Key is valid for? Give an expiry such as
2y. You can extend it later; a key that expires limits the damage if you lose it. - Real name, Email address and an optional Comment, then
Ofor Okay. - A passphrase that protects the private key.
The quick version, with the defaults (Ed25519 for signing, Cv25519 for encryption, expiry after three years in our test):
gpg --quick-generate-key "Alice Admin <alice@example.com>" default default
$ gpg --list-secret-keys --keyid-format long
sec ed25519/9B0FD699BBF751BA 2026-09-30 [SC] [expires: 2029-09-29]
DB92DAB5EE62B1DF2050ADCD9B0FD699BBF751BA
uid [ultimate] Alice Admin <alice@example.com>
ssb cv25519/6D7029415F3160D4 2026-09-30 [E]
The 40-character line is the fingerprint. GnuPG also saves a revocation certificate in ~/.gnupg/openpgp-revocs.d/. Copy it, and an export of the private key (gpg --armor --export-secret-keys alice@example.com > private.asc), to safe offline storage.
2. Share and import public keys
gpg --armor --export alice@example.com > alice.asc # send this file to others gpg --import bob.asc gpg --fingerprint bob@example.com
Compare the fingerprint with the owner over another channel (a call, a signed email). Until you do, encrypting to the key stops with There is no assurance this key belongs to the named user and asks Use this key anyway? (y/N); in a script (--batch) it fails with encryption failed: Unusable public key. Once you have checked the fingerprint, sign the key locally:
gpg --quick-lsign-key 9B6C7935B20900698F5E5E00727498938BC5F3A1
After that gpg --list-keys showed the key as [ full ] and encryption worked.
3. Encrypt and decrypt files
gpg --encrypt --recipient bob@example.com --output secret.txt.gpg secret.txt gpg --output secret.txt --decrypt secret.txt.gpg
Only the holder of Bob’s private key can decrypt. Add --armor for text output you can paste into an email. Add --recipient with your own address too if you want to open the file yourself: when Alice encrypted only for Bob, her own decrypt attempt failed with decryption failed: No secret key.
For a file only you need to open, such as a backup, use a passphrase instead of keys:
gpg --symmetric --cipher-algo AES256 backup.tar.gz # creates backup.tar.gz.gpg gpg --output backup.tar.gz --decrypt backup.tar.gz.gpg
gpg-agent remembers a passphrase for a while: the defaults we found were 600 seconds after last use (default-cache-ttl), 7,200 at most (max-cache-ttl). In our test a second decrypt with a wrong passphrase still worked from the cache, so don’t take that as a passphrase test. gpgconf --kill gpg-agent clears it.
4. Sign and verify
gpg --armor --detach-sign release.tar.gz # creates release.tar.gz.asc gpg --verify release.tar.gz.asc release.tar.gz
gpg: Good signature from "Alice Admin <alice@example.com>" [ultimate]
After one byte was added to the file, the same check printed BAD signature and exited with code 1, so scripts can rely on the exit code. gpg --clearsign message.txt signs a text message but keeps it readable. To verify software you download, import the publisher’s key from their official site, check its fingerprint, then run gpg --verify on the signature file they provide.
5. Keyservers and WKD
GnuPG 2.4 on Debian uses hkps://keys.openpgp.org as its default keyserver:
gpg --keyserver hkps://keys.openpgp.org --recv-keys FINGERPRINT gpg --keyserver hkps://keys.openpgp.org --send-keys FINGERPRINT gpg --locate-external-keys torvalds@kernel.org
Always fetch by full fingerprint, not by name. The last command uses the Web Key Directory (WKD), where a domain publishes its users’ keys; it imported the key for that address in our test. Sending a key to a keyserver publishes it, so only send keys that are meant to be public.
Error: Inappropriate ioctl for device
Over SSH or in a script, signing or decrypting can fail with gpg: signing failed: Inappropriate ioctl for device: gpg-agent can’t find a terminal to ask for the passphrase. The GnuPG manual says to add this to ~/.bashrc:
GPG_TTY=$(tty) export GPG_TTY
For unattended jobs use --batch --pinentry-mode loopback --passphrase-file FILE with a file only root can read, or a separate key used only for that job.
Related: encrypt files with tar and OpenSSL and repository signing keys on Ubuntu.
Official documentation: gpg(1) manual.