---
tags: [freebsd, tooling]
verified: 2026-09-02
---

# FreeBSD — pkg и Ports Collection: управление сторонним софтом

## Обзор

FreeBSD предоставляет две взаимодополняющие технологии для установки стороннего софта: бинарные пакеты (через `pkg(8)`) и Ports Collection (сборка из исходников). Это не конкурирующие системы, а две стороны одной медали: порты — это рецепты сборки, пакеты — результат их применения. Официальные бинарные пакеты собираются из тех же портов на сборочной ферме FreeBSD.

Ключевое отличие от Linux-дистрибутивов: весь сторонний софт устанавливается в `/usr/local`, а не смешивается с base system в `/usr`. Это архитектурное разделение (описанное в статье о файловой структуре) делает обновление base system и пакетов полностью независимыми операциями.

## pkg: бинарные пакеты

### Архитектура

`pkg(8)` — менеджер бинарных пакетов, заменивший устаревший `pkg_install` начиная с FreeBSD 10 (2014). Работает с репозиторием pre-compiled пакетов, автоматически разрешает зависимости, ведёт локальную базу данных установленного софта.

При первом вызове `pkg` на свежей системе автоматически скачивается и устанавливается из `/usr/sbin/pkg` (bootstrap). Поставляемая системой конфигурация репозиториев лежит в `/etc/pkg/FreeBSD.conf`; править её не следует — переопределения и собственные репозитории кладутся в `/usr/local/etc/pkg/repos/`.

Бинарные пакеты собираются на сборочной ферме FreeBSD из дерева портов с дефолтными опциями. Если нужны нестандартные опции сборки — это территория портов или poudriere.

### Репозитории: quarterly vs latest

FreeBSD поддерживает две ветки репозитория:

`quarterly` — обновляется раз в квартал, ориентирован на стабильность. Пакеты получают только security-фиксы и критичные исправления. Используется по умолчанию.

`latest` — актуальные версии, обновляется непрерывно. Ближе к rolling release для стороннего софта.

Переключение на latest:

```sh
mkdir -p /usr/local/etc/pkg/repos
cat > /usr/local/etc/pkg/repos/FreeBSD.conf << 'EOF'
FreeBSD-ports: {
  url: "pkg+https://pkg.FreeBSD.org/${ABI}/latest"
}
EOF
pkg update -f
```

Имя блока обязано совпадать с именем репозитория из `/etc/pkg/FreeBSD.conf`: при несовпадении получится не переопределение, а второй репозиторий рядом с прежним. В FreeBSD 15 этот репозиторий переименован из `FreeBSD` в `FreeBSD-ports`, а рядом с ним появились `FreeBSD-ports-kmods` (модули ядра) и выключенный по умолчанию `FreeBSD-base`. В 14.x имя прежнее — `FreeBSD`.

Trade-off прост: quarterly — для production, где важна предсказуемость; latest — для development или когда нужны свежие версии.

### Основные операции

```sh
pkg update                     # обновить индекс репозитория
pkg search nginx               # поиск пакета
pkg search -o nginx            # поиск с отображением origin (категория/имя)
pkg install nginx              # установка с зависимостями
pkg install -y nginx           # без подтверждения
pkg delete nginx               # удаление
pkg autoremove                 # удалить осиротевшие зависимости
pkg upgrade                    # обновить все пакеты
pkg info                       # список установленных пакетов
pkg info nginx                 # детали конкретного пакета
pkg info -l nginx              # список файлов пакета
pkg info -d nginx              # зависимости пакета
pkg which /usr/local/bin/curl  # какому пакету принадлежит файл
```

### Безопасность и аудит

```sh
pkg audit -F                   # обновить БД уязвимостей и проверить установленные пакеты
pkg check -d -a                # проверить целостность зависимостей всех пакетов
pkg check -s -a                # проверить контрольные суммы файлов
```

`pkg audit` проверяет установленные пакеты по базе VuXML (FreeBSD Vulnerability and Exploits Markup Language). Рекомендуется запускать периодически или после `pkg upgrade`.

### Управление кэшем и блокировкой

```sh
pkg clean                      # удалить устаревшие пакеты из кэша (/var/cache/pkg/)
pkg clean -a                   # удалить весь кэш
pkg lock nginx                 # заблокировать пакет от обновления
pkg unlock nginx               # разблокировать
pkg lock -l                    # список заблокированных
```

Блокировка полезна, когда конкретная версия пакета критична для production и не должна обновляться при `pkg upgrade`.

### Бэкап и восстановление

pkg автоматически бэкапит свою базу данных: ежедневный скрипт `411.pkg-backup` включается переменной `daily_backup_pkg_enable` в `periodic.conf` и складывает сжатые дампы в `/var/backups` (каталог — `daily_backup_pkg_dir`, глубина ротации — `daily_backup_pkg_count`).

Отдельной команды `pkg backup` больше нет: её удалили в pkg 1.19, оставив дамп через sqlite-консоль — ровно то, что делает periodic-скрипт.

```sh
pkg shell .dump > /var/backups/pkg.sql              # дамп /var/db/pkg/local.sqlite
sqlite3 local.sqlite.new < /var/backups/pkg.sql    # восстановление: заливать в чистую базу
```

Схема базы привязана к версии pkg, поэтому periodic-скрипт сохраняет вместе с дампом ещё и `pragma user_version` — при восстановлении на другой версии pkg об этом стоит помнить.

Создание списка установленных пакетов для воспроизведения на другой машине:

```sh
pkg query -e '%a = 0' '%o' > manually_installed.txt   # только вручную установленные
# На другой машине:
xargs pkg install -y < manually_installed.txt
```

Флаг `%a = 0` фильтрует пакеты, установленные как зависимости (`%a = 1`), оставляя только те, что были установлены напрямую.

### Конфигурация pkg

Глобальная конфигурация — `/usr/local/etc/pkg.conf`. Репозитории — `/usr/local/etc/pkg/repos/*.conf`.

Полезные настройки:

```conf
# /usr/local/etc/pkg.conf
ALIAS: {
  up: "upgrade -y",
  in: "install -y",
  rm: "delete -y"
}
```

После этого `pkg up` эквивалентно `pkg upgrade -y`.

## Ports Collection: сборка из исходников

### Архитектура

Ports Collection — это дерево каталогов (`/usr/ports`), где каждый каталог содержит рецепт сборки одного приложения. Рецепт (port skeleton) включает: `Makefile` (инструкции по сборке), `distinfo` (контрольные суммы исходников), `files/` (патчи для FreeBSD), `pkg-descr` (описание), `pkg-plist` (список устанавливаемых файлов).

При сборке порта система автоматически скачивает исходный код из upstream, применяет FreeBSD-специфичные патчи, компилирует, устанавливает и регистрирует результат в базе pkg. Результат установки порта и установки бинарного пакета идентичен — в обоих случаях это запись в локальной базе `pkg`, управляемая через `pkg info`, `pkg delete` и т.д.

Коллекция организована по категориям: `www/nginx`, `databases/postgresql16-server`, `editors/vim`, `security/openssh-portable`, `lang/python311`. По квартальному отчёту за первый квартал 2026 года в дереве почти 38 тысяч портов.

### Когда нужны порты вместо pkg

Порты нужны, когда дефолтные опции сборки не подходят: нужно включить модуль, не включённый в бинарный пакет, или отключить ненужную зависимость. Например, `www/nginx` имеет десятки опциональных модулей, из которых в бинарном пакете включены только базовые.

Другие случаи: нужна версия новее, чем в репозитории; нужна специфическая оптимизация под процессор (CFLAGS); требуется патч, не включённый в upstream.

Для большинства задач на production-сервере бинарных пакетов достаточно. Порты — инструмент для ситуаций, когда стандартная сборка не подходит.

### Получение дерева портов

```sh
# Через git (рекомендуемый способ)
pkg install git-lite
git clone https://git.FreeBSD.org/ports.git /usr/ports

# Quarterly ветка (соответствует quarterly-репозиторию pkg)
# Ветки нарезаются в январе, апреле, июле и октябре: 2026Q1, 2026Q2, 2026Q3, ...
git clone -b 2026Q3 https://git.FreeBSD.org/ports.git /usr/ports

# Обновление
cd /usr/ports && git pull
```

Важно: если используются одновременно pkg и порты, ветка дерева портов должна соответствовать ветке репозитория pkg (quarterly или latest). Несоответствие — основной источник проблем с зависимостями при смешанном использовании.

### Сборка и установка порта

```sh
cd /usr/ports/www/nginx
make config                    # интерактивный выбор опций (curses-диалог)
make install clean             # скачать, собрать, установить, очистить рабочий каталог
```

`make config` сохраняет выбранные опции в `/var/db/ports/<категория>_<порт>/options` — для `www/nginx` это `/var/db/ports/www_nginx/options`. Они запоминаются и применяются при последующих сборках.

Другие полезные make-цели:

```sh
make showconfig                # показать текущие опции без диалога
make rmconfig                  # сбросить опции к дефолтным
make config-recursive          # настроить опции для порта и всех зависимостей
make fetch                     # только скачать исходники
make extract                   # скачать и распаковать
make build                     # скачать, распаковать, собрать (без установки)
make package                   # собрать бинарный пакет (.pkg)
make deinstall                 # удалить установленный порт
make reinstall                 # переустановить
make clean                     # очистить рабочий каталог (work/)
```

Исходники скачиваются в `/usr/ports/distfiles/`. Рабочий каталог — `work/` внутри каталога порта. Оба занимают место и могут быть периодически очищены.

### Структура каталога порта

```text
/usr/ports/www/nginx/
├── Makefile           # основной файл сборки: зависимости, версия, опции, URL
├── distinfo           # SHA256 и размер исходников для верификации
├── pkg-descr          # описание для pkg info
├── pkg-plist          # список файлов, устанавливаемых портом
└── files/
    ├── patch-*        # патчи, применяемые к исходникам
    └── nginx.in       # шаблон rc-скрипта (устанавливается в /usr/local/etc/rc.d/)
```

Makefile порта — не произвольный makefile, а декларативный файл с переменными, интерпретируемый системой фреймворка (`bsd.port.mk`). Типичный Makefile содержит: `PORTNAME`, `PORTVERSION`, `MASTER_SITES` (откуда скачать), `USES` (используемые фреймворки: python, cmake, ssl...), `OPTIONS_DEFINE` (опции сборки).

### Поиск портов

```sh
cd /usr/ports
make search name=nginx                  # поиск по имени
make search key=web\ server             # поиск по ключевым словам
make quicksearch name=redis             # краткий вывод

# Или через pkg (работает и без установленного дерева портов)
pkg search -o nginx                     # origin: www/nginx
```

Онлайн: [freshports.org](https://www.freshports.org/) — наиболее полная и оперативная информация о портах, включая историю изменений и зависимости.

## Смешанное использование pkg и портов

Это самый частый источник путаницы и проблем. Результат установки порта и пакета — одно и то же с точки зрения pkg: запись в базе данных. Но при `pkg upgrade` репозиторий может заменить собранный из порта пакет на бинарный с другими опциями, нарушив зависимости.

Безопасные паттерны:

Только pkg (рекомендуемый для большинства) — используются исключительно бинарные пакеты. Простота, предсказуемость, скорость.

Pkg + несколько портов — бинарные пакеты для всего, порты только для нескольких приложений с нестандартными опциями. Работает, если ветки совпадают (quarterly/latest), но порты-исключения стоит заблокировать через `pkg lock`, чтобы `pkg upgrade` не перезаписал их бинарными версиями.

Только порты через poudriere — все пакеты собираются из портов с нужными опциями в чистом окружении, результат используется как локальный репозиторий для pkg. Наиболее корректный подход для production с кастомизированной сборкой.

## Poudriere: собственный репозиторий

Poudriere — инструмент для сборки пакетов из портов в изолированных jail-окружениях. Каждая сборка происходит в чистом jail, что гарантирует воспроизводимость и отсутствие влияния хост-системы.

Это оптимальный подход, когда нужны кастомные опции сборки, но при этом хочется сохранить удобство управления через `pkg`. Poudriere собирает `.pkg`-файлы, из которых формируется локальный репозиторий. После этого `pkg` настраивается на использование этого репозитория вместо (или вместе с) официального.

Базовый workflow:

```sh
pkg install poudriere

# Создать jail для сборки
poudriere jail -c -j 14amd64 -v 14.4-RELEASE

# Получить дерево портов
poudriere ports -c -p default

# Создать список пакетов для сборки
echo "www/nginx" >> /usr/local/etc/poudriere.d/pkglist
echo "databases/postgresql16-server" >> /usr/local/etc/poudriere.d/pkglist

# Задать опции (интерактивный диалог)
poudriere options -j 14amd64 -p default -f /usr/local/etc/poudriere.d/pkglist

# Собрать
poudriere bulk -j 14amd64 -p default -f /usr/local/etc/poudriere.d/pkglist
```

Результат сборки — готовый репозиторий в `/usr/local/poudriere/data/packages/`. Остаётся настроить pkg на его использование:

```sh
cat > /usr/local/etc/pkg/repos/local.conf << 'EOF'
local: {
  url: "file:///usr/local/poudriere/data/packages/14amd64-default",
  enabled: yes,
  priority: 100
}
EOF
```

`priority: 100` означает, что локальный репозиторий будет предпочтён официальному при совпадении пакетов.

Poudriere заслуживает отдельной статьи — здесь обозначены только базовые принципы.

## Обновление портов

Если порты используются напрямую (без poudriere), обновление требует дополнительных инструментов. Сам фреймворк портов не имеет встроенного `upgrade` — он умеет только устанавливать.

`portmaster` (ports-mgmt/portmaster) — наиболее простой инструмент, не имеющий зависимостей кроме base system:

```sh
pkg install portmaster
portmaster -a                  # обновить все порты
portmaster -a --no-confirm     # без подтверждений
portmaster www/nginx           # обновить конкретный порт
```

`portupgrade` (ports-mgmt/portupgrade) — альтернатива, более мощная, но зависит от Ruby.

В обоих случаях: перед обновлением стоит обновить дерево портов (`cd /usr/ports && git pull`) и проверить `/usr/ports/UPDATING` — файл содержит заметки о портах, требующих особого внимания при обновлении (изменённые зависимости, переименования, миграции конфигов).

## Полезные утилиты для работы с пакетами

```sh
pkg stats                      # общая статистика: сколько пакетов, размер
pkg prime-list                 # только вручную установленные (не зависимости)
pkg query '%n: %sh' | sort -t: -k2 -h   # пакеты по размеру
pkg annotate -A nginx custom_note "production, don't remove"  # пометки
```

## Отличия от Linux-менеджеров пакетов

В отличие от apt/dnf/pacman, где пакетный менеджер управляет и системными пакетами, и пользовательским софтом, `pkg` управляет только сторонним софтом. Base system обновляется отдельно через `freebsd-update` или пересборку из исходников.

Граница, впрочем, размывается. Начиная с 15.0-RELEASE pkgbase (`freebsd-base`) объявлен tech preview для установки системы, минорных и мажорных обновлений: base разложен на пакеты и лежит в репозитории `FreeBSD-base`, который присутствует в `/etc/pkg/FreeBSD.conf`, но выключен по умолчанию. По плану он со временем заменит и наборы дистрибутивов вроде `base.txz`, и `freebsd-update`, но пока это именно предварительный вариант, а не режим по умолчанию.

Нет PPA/COPR/AUR — аналогом является дерево портов, где любой может создать порт для нового софта и отправить его в коммит.

Rollback пакетов не встроен нативно (в отличие от, например, Nix). Но в комбинации с ZFS boot environments или jail'ами можно добиться аналогичного результата.

## Источники

- FreeBSD Handbook, Chapter 4 "Installing Applications: Packages and Ports": [docs.freebsd.org/en/books/handbook/ports/](https://docs.freebsd.org/en/books/handbook/ports/)
- FreeBSD Foundation, "FreeBSD Ports and Packages: What you need to know": [freebsdfoundation.org/blog/freebsd-ports-and-packages-what-you-need-to-know/](https://freebsdfoundation.org/blog/freebsd-ports-and-packages-what-you-need-to-know/)
- FreeBSD Porter's Handbook: [docs.freebsd.org/en/books/porters-handbook/](https://docs.freebsd.org/en/books/porters-handbook/)
- `pkg(8)`: [man.freebsd.org/cgi/man.cgi?query=pkg&sektion=8](https://man.freebsd.org/cgi/man.cgi?query=pkg&sektion=8)
- `pkg.conf(5)`: [man.freebsd.org/cgi/man.cgi?query=pkg.conf&sektion=5](https://man.freebsd.org/cgi/man.cgi?query=pkg.conf&sektion=5)
- `ports(7)`: [man.freebsd.org/cgi/man.cgi?query=ports&sektion=7](https://man.freebsd.org/cgi/man.cgi?query=ports&sektion=7)
- FreshPorts: [freshports.org](https://www.freshports.org/)

---

## Связанные заметки

- [FreeBSD — файловая структура](./freebsd-filesystem-hierarchy.md) — почему пакеты живут в `/usr/local`
- [FreeBSD — обновление системы](./freebsd-updating.md) — согласование версий base system и пакетов
- [FreeBSD — rc-система](./freebsd-rc-system.md) — запуск сервисов, установленных из пакетов
- [Linux — пакетные менеджеры](./linux-package-managers.md) — deb/rpm/pacman, для сравнения
- [FreeBSD — сводный cheatsheet](./freebsd-cheatsheet.md) — быстрая справка по pkg и портам
- [Debian: модель релизов и управление пакетами](./debian-releases-and-packages.md) — заморозка против rolling со стороны Linux; quarterly и latest, для сравнения
