fpm: Build deb, rpm, and macOS Packages From Any Source
Effing package management! Build packages for multiple platforms (deb, rpm, etc) with great ease and sanity.
At a glance
- What is it?
- fpm (Effing Package Management) is a Ruby CLI that converts gem, npm, pip, directory, and archive sources into native OS packages for Debian, Red Hat, macOS, FreeBSD, Solaris, and ArchLinux targets. It takes the place of learning each platform's packaging toolchain.
- Who is it for?
- Operations and release engineers who need to produce native packages for multiple Linux distributions without learning each platform's packaging toolchain should evaluate fpm. It is the wrong tool when a package needs to pass a distribution's official review process, which imposes policy constraints that fpm deliberately sidesteps.
- Can I use it commercially?
- Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
- Is it still maintained?
- Yes. The repository last received commits 15 days ago.
- What is it written in?
- Mainly Ruby, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 22, 2026, and from our analysis. They are not legal advice.
DEEP OPEN-SOURCE ANALYSIS
The Cross-Platform Packaging Problem fpm Addresses
Building a software package for Debian requires learning debhelper, dh_make, and the Debian Policy Manual. Building the same software for Red Hat requires rpmbuild and RPM spec file syntax. Building for macOS requires pkgbuild. The rules, tools, and file formats are entirely different across those platforms, and a team that ships to all three must maintain three separate packaging workflows.
fpm provides a single interface that targets all of them. You describe your package once, point fpm at a source, and it outputs the format the target platform expects. The project README frames this as the core goal: it should be easy to say "here's my install dir and here's some dependencies; please make a package".
The tool was written by Jordan Sissel after moving between Ubuntu and CentOS deployments and finding the incompatible packaging systems a recurring friction. Version 1.18.0 was released on 26 August 2026, and the repository received its last push on 14 September 2026. The project is under active development.
Input Sources: Gems, npm, pip, Directories, and Archives
fpm can build a package from several source types, each handled by a different input driver.
For language ecosystems, fpm supports RubyGems (gem), Python packages (pip), PEAR, and Node.js packages (npm). The README notes that for gem, Python, and PEAR sources, fpm can auto-download the package from the respective registry: you give it the package name and version, and it fetches and repackages it without requiring a local installation first.
For file-based sources, fpm accepts plain directories, tar and tar.gz archives, existing deb packages, existing rpm packages, and ArchLinux pacman packages. The directory source is the most general: build your software, place the files in a staging directory matching the desired install layout, and point fpm at it. This works for any language or runtime that does not have a native package source driver.
The README also lists capabilities beyond building from scratch: tweaking existing packages by removing files or changing metadata, and stripping pre/post/maintainer scripts from a package. This is useful when repackaging a third-party package that includes scripts your environment cannot or should not run.
Output Formats: deb, rpm, macOS, FreeBSD, and More
The target formats fpm supports are deb (Debian/Ubuntu), rpm (Red Hat/CentOS/Fedora), Solaris packages, FreeBSD packages, plain tar archives, directories, Mac OS X .pkg files (the osxpkg format), and ArchLinux pacman packages.
Each target format corresponds to a backend in fpm's Ruby codebase under `lib/`. The project's design means one source type can produce any supported target: an npm package can be converted to a deb, or a directory can be packaged as an rpm, a FreeBSD package, and a macOS pkg all from the same fpm invocation with different flags.
The Dockerfile in the repository shows which OS tools each target format requires at runtime. The minimal base image installs `debsigs`, `pacman`, `rpm`, `squashfs-tools`, and `cpio` among others. A system that will build all supported output types must have those tools available; a system building only deb packages needs a smaller subset. The Dockerfile separates a "minimal" image (core package tools) from an "everything" image that adds scripting languages for the npm, pip, and Perl source drivers.
Installing fpm and What It Depends On at Runtime
fpm is distributed as a Ruby gem. The installation guide is at fpm.readthedocs.io/en/latest/installation.html, and the README links there rather than reproducing the steps inline.
The repository ships a Dockerfile that makes the runtime dependencies explicit. The minimal base stage installs these OS packages on Ubuntu 20.04 to support the core package-building formats:
apt-get install --no-install-recommends --no-install-suggests -y \
'ruby=*' \
'ruby-dev=*' \
'libarchive-tools=*' \
'cpio=*' \
'debsigs=*' \
'pacman=*' \
'rpm=*'A separate "everything" stage in the Dockerfile adds Python 3, Node.js (npm), and Perl to support the pip, npm, and PEAR input drivers. Teams using only the directory or tar source types with deb/rpm targets need only the minimal set.
To build the gem from the repository source, the Makefile's gem recipe runs:
gem build $(GEMSPEC)The install target then runs:
gem install $(GEM)The Makefile also defines a Docker-based test workflow. The `docker-test-minimal` and `docker-test-everything` targets build images tagged `fpm-test-minimal` and `fpm-test-everything`, then run the rspec suite inside them. The Dockerfile uses BuildKit syntax and requires `DOCKER_BUILDKIT=1` when invoking the build step.
Tweaking and Repackaging Existing Packages
One use case that distinguishes fpm from writing packages from scratch is repackaging. The README describes taking an existing deb or rpm, removing files, changing metadata or dependencies, or stripping pre/post/maintainer scripts, and producing a modified package.
This matters in environments where a vendor-supplied package installs files in locations that conflict with local policy, or where a package's postinstall script performs actions incompatible with the deployment environment, such as starting a service that the configuration management system should control. fpm lets the operator produce a clean replacement without forking the package's source tree.
The deb and rpm source types both accept existing packages as input. Combined with any of the supported output formats, fpm can convert a deb to an rpm or vice versa, which is useful when a vendor supplies only one package format but the deployment target requires another.
Where fpm Is the Wrong Tool
fpm deliberately avoids enforcing packaging policy. The README states its goal as making packaging easy and quick, which means it will produce packages that would not pass the Debian Policy Manual or Fedora Packaging Guidelines review. Packages destined for inclusion in an official Linux distribution repository must be built with the correct platform toolchain and meet that distribution's specific rules: lintian for Debian, rpmlint for Red Hat. fpm produces packages that install correctly, but they may have policy violations that official tooling would reject.
fpm is a Ruby application that requires Ruby at runtime. Environments where Ruby is not available or cannot be installed add a dependency just to run the build tool. The Dockerfile approach sidesteps this on systems where Docker is available, but introduces its own dependency.
The project README and search data show that fpm's name overlaps with the Fortran Package Manager, which also uses the fpm acronym. The `jordansissel/fpm` repository is the package-building tool; searches that return Fortran Package Manager results are returning a different project.
Maintaining cross-platform package outputs also means the team must test each format separately. fpm can produce the files, but verifying that an rpm installs correctly on Rocky Linux and that a deb installs correctly on Ubuntu Focal requires separate test environments.
fpm Compared to nfpm
nfpm (Not FPM) is a Go-based packaging tool that targets deb, rpm, apk (Alpine), and Arch packages. The related searches show users comparing the two directly.
The practical difference is in the source model. fpm builds from multiple source types including existing language-ecosystem packages (gems, pip, npm), and it can consume existing OS packages as inputs. nfpm's model is configuration-file-driven: you write an nfpm.yaml that declares the files to include, and nfpm packages them. nfpm does not auto-download from language registries.
nfpm integrates with GoReleaser, a Go project release tool, which makes it a common choice in Go project CI pipelines. The related searches for nfpm specifically mention GoReleaser. fpm has no comparable native integration with a Go build chain.
For teams that need to repackage existing language-ecosystem software (converting a Python pip package to a deb, for example), fpm's auto-download drivers reduce manual steps that nfpm requires explicitly. For teams building from a file tree they already control, either tool can serve the job.
Editorial conclusion
Operations and release engineers who need to produce native packages for multiple Linux distributions without learning each platform's packaging toolchain should evaluate fpm. It is the wrong tool when a package needs to pass a distribution's official review process, which imposes policy constraints that fpm deliberately sidesteps. The repository's LICENSE file is present but the SPDX identifier in the package metadata reads NOASSERTION, so verify the licence terms directly from the repository before distributing packages built by fpm commercially.
Frequently asked questions
What is fpm (Effing Package Management)?
fpm is a Ruby CLI tool that builds native OS packages from multiple input sources, including gem, pip, npm, directories, and archives. It targets output formats including deb, rpm, macOS pkg, FreeBSD, and ArchLinux pacman packages, avoiding the need to learn each platform's native packaging toolchain.
What input sources does fpm support?
fpm accepts RubyGems, Python (pip), PEAR, Node.js (npm), directories, tar archives, existing deb packages, existing rpm packages, and ArchLinux pacman packages as input sources. For gem, pip, and PEAR sources, fpm can auto-download the package from the registry by name.
How do I install fpm?
The README links to the installation guide at fpm.readthedocs.io/en/latest/installation.html for platform-specific instructions. To install from the repository source, the Makefile provides a make install target that builds the gem and installs it locally.
Can fpm convert a deb package to an rpm?
Yes. fpm accepts an existing deb package as an input source and can output an rpm. The same conversion works in reverse and across other supported format pairs.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/jordansissel-fpm)
Community notes