Skip to content

How to Use GnuPG (gpg) on Linux: Create Keys, Encrypt, Sign and Use Keyservers

5 min read

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 O for 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.

Related services

KVM VPS hosting

NVMe SSD and full root access, with Free Basic Managed Support.

Unmanaged dedicated servers

full root access and free IPMI KVM, with Free Basic Managed Support.

Linux server management

hardening, patching, monitoring and automation for Ubuntu, Debian, RHEL and AlmaLinux.

Was this answer helpful?

Still stuck? Open a ticket