This guide explains how to create FreeBSD packages for your projects and host them in custom repositories.
Create pkg-manifest.ucl with your package metadata:
name: "yourapp"
version: "1.0.0"
origin: "category/yourapp"
comment: "Brief description of your app"
arch: "freebsd:14:x86:64"
www: "https://your-project-url.com"
maintainer: "[email protected]"
prefix: "/usr/local"
desc: <<EOD
Longer description of your application.
Can be multiple lines.
EOD
categories: ["sysutils"]
licenselogic: "single"
licenses: ["MIT"]
Create pkg-plist listing files to include (relative to /usr/local):
bin/yourapp
share/doc/yourapp/README.md
share/doc/yourapp/LICENSE
Create build-package.sh to automate the build process:
#!/bin/sh
# Build and create FreeBSD package
set -e
echo "Building application..."
# Replace with your build command
zig build -Doptimize=ReleaseFast
# or: make
# or: cargo build --release
echo "Preparing staging area..."
rm -rf pkg-staging
mkdir -p pkg-staging/usr/local/bin
mkdir -p pkg-staging/usr/local/share/doc/yourapp
echo "Copying files..."
# Adjust paths for your project
cp zig-out/bin/yourapp pkg-staging/usr/local/bin/
cp README.md LICENSE pkg-staging/usr/local/share/doc/yourapp/
echo "Creating package..."
mkdir -p packages/All
pkg create -M ./pkg-manifest.ucl -p ./pkg-plist -r ./pkg-staging -o ./packages/All/
echo "Generating repository metadata..."
pkg repo ./packages/
echo "Package created in ./packages/"Make it executable: chmod +x build-package.sh
pkg-manifest.ucl- Package metadatapkg-plist- File listbuild-package.sh- Build script
Don't check in:
pkg-staging/- Generated during buildpackages/- Build output*.pkgfiles
-
Build the package:
./build-package.sh
-
Create a repo config at
/usr/local/etc/pkg/repos/yourapp-local.conf:yourapp-local: { url: "file:///path/to/your/project/packages/", enabled: yes, priority: 10 } -
Install from local repo:
sudo pkg update sudo pkg install yourapp
Each project gets its own repository directory:
/var/www/
├── project1/
│ ├── All/
│ │ ├── project1-0.1.0.pkg
│ │ └── project1-0.2.0.pkg
│ ├── packagesite.pkg
│ └── meta
├── project2/
│ ├── All/
│ │ └── project2-1.0.0.pkg
│ ├── packagesite.pkg
│ └── meta
In your CI pipeline (which must run on FreeBSD):
-
Update version in
pkg-manifest.ucl(can be automated from git tags) -
Build the package:
./build-package.sh
-
Deploy to web server:
rsync -av --delete ./packages/ server:/var/www/yourproject/
Users add a repository configuration to /usr/local/etc/pkg/repos/yourproject.conf:
yourproject: {
url: "https://example.com/yourproject/",
enabled: yes
}
Then install:
sudo pkg update
sudo pkg install yourappname: Build Package
on:
push:
tags:
- 'v*'
jobs:
build:
runs-on: [self-hosted, freebsd] # Requires FreeBSD runner
steps:
- uses: actions/checkout@v2
- name: Update version
run: |
VERSION=${GITHUB_REF#refs/tags/v}
sed -i '' "s/version: \".*\"/version: \"$VERSION\"/" pkg-manifest.ucl
- name: Build package
run: ./build-package.sh
- name: Deploy to server
run: |
rsync -av --delete ./packages/ user@server:/var/www/myproject/When hosting multiple projects:
-
Each project maintains its own:
- Package manifest and plist
- Build script
- CI pipeline
- Web directory (
/var/www/projectname/) - Repository config file
-
Users can install from multiple repositories by adding multiple
.conffiles:/usr/local/etc/pkg/repos/project1.conf /usr/local/etc/pkg/repos/project2.conf /usr/local/etc/pkg/repos/project3.conf
-
Benefits of separate repositories:
- No cross-project dependencies in CI
- No bandwidth waste copying other projects' packages
- Each project can deploy independently
- Simpler CI pipelines
- The
pkg repocommand must run on FreeBSD (regenerates metadata) - Repository metadata files (outside
All/) are regenerated each time - Package files in
All/accumulate (multiple versions can coexist) - Users can install specific versions:
pkg install yourapp-1.0.0 - The web server doesn't need to be FreeBSD, just serve static files
- Consider signing packages for production use
- Use HTTPS for repository URLs
- Restrict rsync/SSH access to CI systems only
- Keep older package versions for rollback capability