The scenario
You downloaded a .rpm package from a vendor website or added a third-party repository to your Fedora system. You run sudo dnf install ./package.rpm and the terminal immediately halts. It prints a hard stop about a missing public key or a failed GPG check. The package manager refuses to touch the file. You know the software is legitimate, but Fedora security model is blocking the installation. You need to import the correct GPG key so the package manager trusts the signature.
What the GPG check actually does
Fedora does not trust software by default. Every package in the official repositories is cryptographically signed by the Fedora Project. When you run dnf, the package manager checks the signature against a set of public keys stored in the RPM database. If the signature matches a trusted key, the installation proceeds. If it does not, dnf aborts to prevent you from running tampered or malicious binaries.
Think of the GPG key like a wax seal on a diplomatic envelope. The seal proves the sender and guarantees the contents were not opened in transit. Fedora ships with the Fedora Project seals pre-installed. Third-party vendors ship their own seals. You must manually add their seal to your trusted collection before Fedora will accept their packages.
The RPM database stores these keys in /var/lib/rpm/. The actual key files live in /etc/pki/rpm-gpg/. Config files in /etc/ are user-modified. Files in /usr/lib/ ship with the package. Edit /etc/. Never edit /usr/lib/. This separation keeps your custom keys safe across system updates.
The gpgcheck directive in repository configuration files controls this behavior. When gpgcheck=1, dnf refuses to install any package that lacks a valid signature from a key in your RPM database. When gpgcheck=0, the package manager skips verification entirely. Disabling GPG checks is a supply chain risk. Only do it in isolated test environments where you control the network and the binaries.
Importing keys the right way
You have two paths depending on how you are adding the software. Use the rpm command for standalone key files or local builds. Use dnf for repository integration.
Here is how to import a standalone GPG key file directly into the RPM database.
# Download the key to a temporary location first
curl -o /tmp/RPM-GPG-KEY-vendor https://example.com/RPM-GPG-KEY-vendor
# Verify the fingerprint before importing. Never skip this step.
gpg --show-keys /tmp/RPM-GPG-KEY-vendor
# Import the key into the system RPM database
sudo rpm --import /tmp/RPM-GPG-KEY-vendor
# Clean up the temporary file
rm /tmp/RPM-GPG-KEY-vendor
The rpm --import command reads the ASCII-armored or binary key file and writes it to the RPM keyring. It does not modify your dnf configuration. The key becomes globally trusted for any package signed with that ID.
Here is how to add a repository and let dnf handle the key automatically.
# Add the repository definition to the dnf configuration directory
sudo dnf config-manager --add-repo https://example.com/repo.repo
# Refresh metadata and trigger automatic key import
sudo dnf upgrade --refresh
# Check the newly added repository status
dnf repolist enabled
The --add-repo flag drops a .repo file into /etc/yum.repos.d/. The file contains a gpgkey= directive pointing to the vendor public key URL. When you run dnf upgrade --refresh, dnf fetches the repository metadata, notices the missing key, downloads it, and imports it into the RPM database automatically. This is the standard weekly maintenance command. dnf system-upgrade is for crossing major Fedora releases. They are different commands. Don't conflate them.
Here is what a properly configured repository file looks like.
[vendor-repo]
name=Vendor Official Repository
baseurl=https://example.com/packages/fedora/$releasever/$basearch
enabled=1
# Require cryptographic verification for all packages in this repo
gpgcheck=1
# Point dnf to the public key URL for automatic import
gpgkey=https://example.com/RPM-GPG-KEY-vendor
# Skip signature check for the metadata file itself to speed up refreshes
repo_gpgcheck=0
The repo_gpgcheck=0 line is a common optimization. Repository metadata files are rarely signed, but package payloads always are. Skipping metadata verification prevents unnecessary network round trips while keeping the actual binaries protected.
Verify the signature before you install
Importing a key does not mean the package is safe. It only means Fedora will stop blocking it. You should verify the signature of a downloaded package before handing it to the package manager.
Here is how to check a local RPM file against your trusted keys.
# Verify the package signature and checksum
rpm -K /path/to/package.rpm
# Check which key ID signed the package
rpm -qpi /path/to/package.rpm | grep "Signature"
# List all currently trusted public keys in the RPM database
rpm -qa gpg-pubkey
The rpm -K command runs a dry-run verification. It prints OK if the signature matches a key in your database and the package checksum is intact. It prints a failure message if the key is missing or the file was altered. Always run this before dnf install or rpm -i on third-party binaries.
Cross-reference the key ID from the rpm -qpi output with the vendor documentation. A mismatched ID means you downloaded the wrong key or the vendor rotated their signing certificate. Verify the fingerprint manually. Trust the cryptographic hash, not the filename.
Common pitfalls and error messages
You will encounter specific error strings when the trust chain breaks. Recognizing them saves time.
error: package vendor-app-1.0-1.x86_64: GPG check FAILED
This error means the package is signed, but the signing key is not in your RPM database. Import the correct key or remove the gpgcheck=1 directive from the repo file. Disabling GPG checks is a supply chain risk. Only do it in isolated test environments.
error: vendor-app-1.0-1.x86_64: Header V4 RSA/SHA256 Signature, key ID ABC12345: NOKEY
This error means dnf knows a key is required but has not fetched it yet. Run sudo dnf upgrade --refresh to trigger the automatic fetch. If the vendor key server is down, download the key manually and use rpm --import.
Fedora uses SELinux in enforcing mode by default. If you are importing keys into a non-standard location or running custom scripts, ensure the context is correct using restorecon if necessary. Standard /etc/pki/rpm-gpg/ paths are handled automatically. SELinux denials show up in journalctl -t setroubleshoot with a one-line summary. Read those before disabling SELinux.
Keys expire. Vendors rotate them. When a vendor publishes a new key, you must remove the old one before importing the replacement. The RPM database does not allow duplicate key IDs.
Here is how to remove an expired or revoked key.
# Find the exact package name for the key you want to remove
rpm -qa gpg-pubkey | grep -i vendor
# Remove the key from the RPM database
sudo rpm -e gpg-pubkey-<key-id>-<timestamp>
# Verify the key is gone
rpm -qa gpg-pubkey | grep -i vendor
The rpm -e command treats keys like regular packages. You must provide the full name including the timestamp suffix. The timestamp ensures you remove the exact version you intend to drop.
Network timeouts during dnf upgrade --refresh often masquerade as missing keys. The package manager tries to fetch the key URL, fails to reach the server, and reports NOKEY. Check your DNS and firewall rules before assuming the key is invalid. Run journalctl -xeu dnf to see the actual network failure. Read the actual error before guessing.
Which method to use
Use rpm --import when you have a standalone key file or are verifying a local build outside of a repository. Use dnf config-manager --add-repo when you are adding a third-party repository and want automatic key management. Use rpm -K when you downloaded a binary from a website and need to verify it before installation. Use rpm -e gpg-pubkey-* when a vendor rotates their signing key or you are decommissioning a repository. Trust the package manager. Manual file edits drift, snapshots stay.