Install from source RPM

A source RPM (SRPM) lets you download the exact source and spec file used to build a Fedora package, so you can rebuild it locally with custom patches or options.

The scenario

You need a feature that only exists in the latest upstream release, or you want to strip out a telemetry module that Fedora's default build includes. The binary in the official repository does not match your hardware or your workflow. You decide to rebuild the package yourself. That means working with a source RPM.

What a source RPM actually contains

A source RPM is not a compiler. It is a blueprint. It contains the original upstream tarball, a list of distribution patches, and a spec file that tells the build system exactly how to patch, configure, compile, and package the software. Think of it like a recipe book. The upstream tarball is the raw ingredient. The spec file is the chef's instructions. Your system provides the kitchen and the stove. When you run the build, you are asking Fedora's packaging tools to follow that recipe on your exact hardware and kernel.

The spec file controls every phase of the build. It defines which patches to apply, which configure flags to pass, which files to copy into the staging directory, and which files belong to the final package. Fedora maintainers write these files to ensure consistency across the distribution. When you rebuild locally, you inherit that consistency while gaining the ability to modify the instructions.

Read the spec file before you change anything. The build will fail if you break the file list or skip a required patch.

Set up the build environment

You need the tools that read spec files and manage the build tree. Fedora keeps these out of the base system to save space on minimal installs. Run the installation command to pull them in.

sudo dnf install rpm-build rpmdevtools dnf-plugins-core
# rpm-build provides rpmbuild and the core macros
# rpmdevtools adds helper scripts for developers
# dnf-plugins-core enables the builddep plugin for dependency resolution

Initialize the directory structure next. The RPM build process expects a specific layout. It separates sources, specs, build artifacts, and final packages to prevent cross-contamination between builds.

rpmdev-setuptree
# creates ~/rpmbuild/{SOURCES,SPECS,BUILD,BUILDROOT,RPMS,SRPMS}
# SOURCES holds tarballs and patches
# SPECS holds the .spec files that drive the build
# BUILD is a temporary workspace for compilation
# RPMS stores the finished binary packages

The build tree lives in your home directory by default. Never run rpmbuild as root. Building as root breaks file ownership rules and can corrupt your system if a buggy spec file executes arbitrary commands during the install phase.

Initialize the tree once. Reuse it for every package you build.

Fetch and unpack the source

You can pull the SRPM directly from the enabled repositories. This ensures you get the exact version that matches your Fedora release.

dnf download --source htop
# fetches the SRPM from the configured repos
# places it in the current working directory
# skips downloading if the file already exists

Install the SRPM afterward. This does not install the software. It extracts the spec file and the source tarballs into the correct directories inside your build tree.

rpm -ivh htop-*.src.rpm
# -i installs the SRPM into the local rpm database
# -v prints verbose output for tracking
# -h shows progress hashes
# extracts spec to ~/rpmbuild/SPECS and sources to ~/rpmbuild/SOURCES

Check the SPECS directory. The spec file should be there. Check SOURCES. The tarball and patches should be present. If the directories are empty, the SRPM failed to extract. Re-run the installation command with the -vv flag to see where the files went.

Verify the extraction before touching the spec file. Missing sources cause silent build failures later.

Resolve dependencies and compile

The spec file lists every library and tool required to compile the package. Your system probably lacks most of them. Use DNF to read the spec file and install the build requirements automatically.

sudo dnf builddep ~/rpmbuild/SPECS/htop.spec
# reads the BuildRequires tags from the spec file
# resolves dependencies against enabled repositories
# installs development headers and compilation tools

Run the build next. The -bb flag tells the tool to skip creating a new SRPM and only produce the binary RPMs. The process will download sources if they are missing, apply patches, run the configure script, compile the code, and stage the files into a temporary root.

rpmbuild -bb ~/rpmbuild/SPECS/htop.spec
# -bb builds only binary RPMs from the spec file
# runs %prep, %build, and %install phases sequentially
# stages files into BUILDROOT before packaging
# writes finished packages to ~/rpmbuild/RPMS/

Watch the terminal output carefully. The build runs in a chroot-like environment inside your ~/rpmbuild/BUILD directory. If it fails, the error will appear at the bottom of the output. Do not scroll past it. The first error is usually the real one. Subsequent errors are just the compiler complaining about missing symbols caused by the first failure.

Let the build finish completely before troubleshooting. Interrupting it leaves partial artifacts that confuse the next run.

Install the rebuilt package

The compiled packages land in ~/rpmbuild/RPMS/. They are organized by architecture. Use DNF to install them. DNF will resolve any runtime dependencies that the spec file missed and register the package with the system database.

sudo dnf install ~/rpmbuild/RPMS/x86_64/htop-*.rpm
# installs local RPM files through DNF's transaction system
# resolves missing runtime dependencies automatically
# registers the package in the rpm database
# prevents dependency conflicts by checking the transaction first

Run rpm -q --queryformat '%{VERSION}-%{RELEASE}\n' htop to confirm the version matches your build. Run rpm -V htop to verify file checksums and permissions. A clean run means the installation is intact.

Check the package database after installation. DNF tracks local builds differently from repository packages.

Common pitfalls and error messages

Builds fail for predictable reasons. Missing build dependencies are the most common. If you see error: Failed build dependencies:, the dnf builddep command either failed or you edited the spec file and added new requirements. Re-run dnf builddep with the updated spec file.

Another frequent issue is SELinux blocking the build process. If the build hangs or fails with permission denied errors, check the audit log.

sudo ausearch -m avc -ts recent
# searches the audit log for SELinux access vector cache denials
# -m avc filters for module-specific denials
# -ts recent shows events from the last session
# reveals which process was blocked and why

Spec files sometimes contain architecture-specific logic. If you are building on ARM and the spec assumes x86_64, the configure script will abort. Read the error message. It will explicitly state which architecture check failed.

Never edit files in /usr/lib/ or /usr/share/ to fix a build. Those directories are owned by packages. If you need to change compile flags or apply a custom patch, edit the spec file in ~/rpmbuild/SPECS/. The spec file is the single source of truth for the build.

Clean the build directory before retrying. Stale objects cause cryptic linker errors.

When to rebuild from source versus other approaches

Use a local SRPM rebuild when you need a specific patch or compile-time flag that the official repository does not provide. Use the official DNF repository when you want automatic security updates and dependency resolution. Use mock when you need a reproducible build that matches Fedora's Koji infrastructure exactly. Use a container or VM when you want to test the build without risking your host system's package database. Stay on the upstream binary package if your only goal is to run the software and you do not need custom modifications.

Pick the tool that matches your risk tolerance. Local builds are fast but fragile. Mock builds are slow but reliable.

Where to go next