How to Create a FreeBSD Package with `pkg-create` on FreeBSD Operating System

Learn how to create custom FreeBSD packages using the pkg-create utility, with practical examples and best practices.

Introduction

FreeBSD is renowned for its stability, security, and performance as a server operating system. One of its strongest features is its package management system, which allows administrators to easily install, upgrade, and remove software. While most users are familiar with using pkg install to install packages, FreeBSD also provides tools to create custom packages. This capability is particularly valuable for system administrators who need to deploy consistent software configurations across multiple systems or maintain private package repositories.

This article provides a comprehensive guide to creating FreeBSD packages using the pkg-create utility. We’ll explore the entire process from preparing the build environment to distributing your custom packages, with practical examples and best practices.

Understanding FreeBSD Packaging

Before diving into package creation, it’s important to understand the basic concepts of FreeBSD’s packaging system:

  • Ports Collection: FreeBSD’s Ports Collection is a framework that allows for easy building of software from source code. It contains makefiles, patches, and file descriptions needed to compile and install software.
  • Packages: Binary packages are pre-compiled versions of software from the Ports Collection, ready to install without compilation.
  • pkg: FreeBSD’s package management tool that handles installation, removal, and upgrading of binary packages.

Creating your own packages offers several advantages:

  1. Consistency: Ensure identical software installations across multiple systems
  2. Customization: Build software with specific compile-time options
  3. Control: Maintain private repositories with custom software
  4. Efficiency: Install packages quickly without compilation time

Prerequisites

Before creating FreeBSD packages, ensure you have:

  • A FreeBSD system (version 12.0 or newer recommended)
  • Root or sudo access
  • Ports Collection installed (/usr/ports)
  • The pkg tool installed (included by default in recent FreeBSD versions)
  • Sufficient disk space (varies depending on the software being packaged)

Methods for Creating FreeBSD Packages

There are several approaches to creating FreeBSD packages:

  1. Using pkg-create: Create packages from installed software
  2. Using the Ports Collection: Build packages directly from ports
  3. Using poudriere: Build packages in a clean jail environment (recommended for production)

This article focuses primarily on the pkg-create method, but we’ll briefly touch on the other approaches for context.

Creating Packages with pkg-create

Basic Usage

The pkg-create command creates a package from files already installed on your system. The basic syntax is:

pkg create -r /path/to/root [-m /path/to/manifest] [-o outdir] [pkg-name]

Where:

  • -r: Specifies the root directory where the files are installed
  • -m: Specifies a custom manifest file (optional)
  • -o: Specifies the output directory for the package
  • pkg-name: Limits the operation to the named package(s)

Step-by-Step Process

1. Install the Software

First, install the software you want to package. You can use either the ports system or the binary package manager:

# Using packages
pkg install nginx

# Using ports
cd /usr/ports/www/nginx
make install clean

2. Create the Package

Once the software is installed, you can create a package with pkg-create:

pkg create -o /tmp nginx

This command creates a package file for nginx in the /tmp directory. The resulting file will have a name like nginx-1.20.2,2.txz.

3. Examine the Package

You can examine the contents of your newly created package:

pkg info -F /tmp/nginx-1.20.2,2.txz

Creating Packages from Multiple Installed Software

To create packages for all installed software:

pkg create -a -o /path/to/output

Where:

  • -a: Creates packages for all installed software

Creating a Package with Custom Manifest

For more control, you can create a package with a custom manifest:

  1. Generate a template manifest:
pkg info -o nginx > nginx.ucl
  1. Edit the manifest file to customize metadata:
# Package metadata
name = "custom-nginx"
version = "1.0.0"
origin = "www/custom-nginx"
comment = "Custom nginx package"
desc = "This is a customized nginx package for internal use"
maintainer = "admin@example.com"
www = "https://example.com"
prefix = "/usr/local"

# Dependencies
deps {
    pcre: {origin: "devel/pcre", version: "8.45"}
    openssl: {origin: "security/openssl", version: "1.1.1k,1"}
}

# Files
files {
    /usr/local/sbin/nginx = "0755";
    /usr/local/etc/nginx/nginx.conf = "0644";
    # Add all relevant files here
}
  1. Create the package with the custom manifest:
pkg create -m nginx.ucl -r / -o /tmp

Creating Packages from the Ports Collection

While pkg-create works with installed software, you can also build packages directly from the Ports Collection:

cd /usr/ports/www/nginx
make package

The resulting package will be stored in /usr/ports/packages or can be customized with:

make PACKAGES=/path/to/packages package

Advanced Package Creation with Poudriere

For production environments, poudriere is the recommended tool for building packages. It creates packages in a clean jail environment, ensuring consistency and preventing contamination from your host system.

Basic poudriere setup:

  1. Install poudriere:
pkg install poudriere
  1. Configure poudriere in /usr/local/etc/poudriere.conf

  2. Create a jail:

poudriere jail -c -j 13amd64 -v 13.1-RELEASE -a amd64
  1. Create a ports tree:
poudriere ports -c -p main
  1. Build packages:
poudriere bulk -j 13amd64 -p main www/nginx

Poudriere will create packages in its configured package directory, typically /usr/local/poudriere/data/packages/.

Testing Your Package

Before distributing your package, it’s important to test it:

  1. Install the package on a test system:
pkg add /path/to/package.txz
  1. Verify that the software works as expected
  2. Test upgrade and removal procedures:
pkg delete package-name

Creating a Local Package Repository

To distribute your packages to multiple systems, create a local package repository:

  1. Collect your packages in a directory:
mkdir -p /usr/local/www/packages
cp /path/to/packages/*.txz /usr/local/www/packages/
  1. Create a package repository catalog:
pkg repo /usr/local/www/packages
  1. On client systems, add the repository to /etc/pkg/custom.conf:
custom: {
    url: "http://your-server/packages",
    enabled: yes,
    priority: 100
}
  1. Update the repository catalog on clients:
pkg update

Best Practices for Package Creation

Documentation

Always document your custom packages, including:

  • Build options used
  • Modifications made to the original software
  • Dependencies
  • Configuration requirements

Version Control

Maintain your custom package definitions in a version control system like Git to track changes and facilitate collaboration.

Automation

Automate the package building process with scripts or tools like Jenkins to ensure consistency and reduce manual errors.

Testing

Implement a testing framework to verify that packages meet your requirements before deployment.

Troubleshooting Common Issues

Package Creation Fails

If package creation fails, check:

  • Disk space: Ensure sufficient space is available
  • Permissions: Verify you have the necessary permissions to create files
  • Dependencies: Make sure all dependencies are correctly installed

Package Installation Fails

If installing your package fails:

  • Check package integrity: pkg check -s package-name
  • Verify dependencies: Ensure all required dependencies are available
  • Check for conflicts: Look for conflicts with existing installed software

Conflicting Files

If your package conflicts with files from other packages:

  • Use custom prefixes to avoid conflicts
  • Create packages that don’t include conflicting files
  • Use configuration management tools like Ansible to handle file conflicts

Conclusion

Creating custom FreeBSD packages with pkg-create provides a powerful way to manage software deployment across multiple systems. By following the steps and best practices outlined in this article, you can build, test, and distribute packages that meet your specific requirements.

While pkg-create offers a straightforward approach for simple packaging needs, tools like poudriere provide more robust solutions for production environments. Depending on your requirements, you might use a combination of these tools to create a comprehensive package management system.

FreeBSD’s flexible packaging system is one of its greatest strengths as a server operating system, and mastering package creation allows you to leverage this capability to its fullest extent.

Further Resources