aft-app: сборка приложений из deb-пакетов#

aft-app — инструмент для создания Flatpak-приложений из существующих deb-пакетов. Принимает на вход YAML-манифест (или параметры командной строки), анализирует зависимости указанного пакета, загружает недостающие библиотеки, формирует структуру Flatpak и экспортирует результат в OSTree-репозиторий.

Команды#

aft-app предоставляет следующие команды:

build#

Сборка приложения по YAML-манифесту:

sudo aft-app build <файл.yaml>

Если манифест содержит несколько документов (разделённых ---), каждый документ обрабатывается последовательно. Ошибка в одном документе не прерывает обработку остальных. По завершении выводится итог: Итого: N/M сборок завершено успешно.

package#

Сборка приложения из параметров командной строки (без манифеста):

sudo aft-app package --id org.example.MyApp --package myapp --runtime org.example.Platform --runtime-version stable --command myapp

Все параметры, которые в манифесте задаются полями YAML, здесь указываются как аргументы командной строки.

analyze#

Анализ зависимостей deb-пакета без выполнения сборки:

aft-app analyze --package myapp

С указанием рантайма для сравнения:

aft-app analyze --package myapp --runtime org.example.Platform --runtime-version stable

Команда выводит список всех зависимостей пакета и отмечает, какие из них уже присутствуют в рантайме, а какие необходимо включить в приложение.

validate#

Проверка корректности манифеста:

aft-app validate <файл.yaml>

Не требует привилегий суперпользователя.

generate-manifest#

Открытие интерактивного генератора манифестов в браузере:

aft-app generate-manifest
aft-app -G

clean#

Очистка кеша загруженных пакетов:

aft-app clean

help#

Вывод справки:

aft-app help
aft-app --help

Параметры команды package#

Ниже перечислены все параметры команды package с указанием обязательности и значений по умолчанию.

Метаданные#

Параметр

Обязательный

Описание

-i, --id

Да

Идентификатор приложения (обратный DNS, например org.example.MyApp)

-n, --name

Нет

Отображаемое имя приложения

-V, --version

Да

Версия приложения

-a, --arch

Нет

Архитектура. Допустимые значения: amd64, arm64, i386, armhf. По умолчанию: amd64

Рантайм и SDK#

Параметр

Обязательный

Описание

-r, --runtime

Да

Идентификатор рантайма

-R, --runtime-version

Да

Версия (ветка) рантайма

-s, --sdk

Нет

Идентификатор SDK. По умолчанию: <идентификатор-рантайма>Sdk

Исходный пакет#

Параметр

Обязательный

Описание

-p, --package

Да

Имя deb-пакета

-c, --command

Да

Команда запуска (имя исполняемого файла)

Разрешения#

Все параметры разрешений можно указывать многократно.

Параметр

Описание

--socket

Сокеты: x11, wayland, pulseaudio, cups, pcsc, ssh-auth, session-bus, system-bus, fallback-x11

--device

Устройства: dri, kvm, shm, all

--share

Разделяемые ресурсы: network, ipc

--filesystem

Доступ к файловой системе: home, host, host-os, host-etc, xdg-desktop, xdg-documents, xdg-download, xdg-music, xdg-pictures, xdg-videos, /абсолютный/путь, ~/относительный/путь

--persist

Персистентные каталоги: .config, .cache, .local/share

--own-name

Имя на сессионной шине D-Bus (own)

--talk-name

Имя на сессионной шине D-Bus (talk)

--system-own-name

Имя на системной шине D-Bus (own)

--system-talk-name

Имя на системной шине D-Bus (talk)

Экспорт и подпись#

Параметр

Обязательный

Описание

-o, --output

Нет

Путь к OSTree-репозиторию. По умолчанию: ./repo

-g, --gpg-sign

Нет

Идентификатор GPG-ключа для подписи

--gpg-homedir

Нет

Каталог GPG-ключей. По умолчанию: ~/.gnupg

--sbom

Нет

Генерировать SBOM (включено по умолчанию)

--no-sbom

Нет

Отключить генерацию SBOM

AppStream и интеграция с рабочим столом#

Параметр

Описание

--metainfo

Путь к файлу AppStream-метаданных (.metainfo.xml или .appdata.xml)

--desktop

Путь к файлу .desktop

--icons-dir

Каталог с иконками (структура: <размер>/имя.png, например 128x128/myapp.png)

Pre-export команды#

--pre-export-cmd

Команда, выполняемая в сборочном каталоге перед экспортом в репозиторий (можно указывать многократно). Рабочий каталог — корень структуры Flatpak (содержит files/, export/, metadata).

sudo aft-app package ... \
    --pre-export-cmd "sed -i 's/old/new/g' files/bin/wrapper.sh" \
    --pre-export-cmd "rm -rf files/share/doc"

Подпись ELF-файлов (bsign)#

Параметр

Описание

--bsign

Включить подпись ELF-файлов через bsign

--bsign-key

Идентификатор GPG-ключа для bsign (включает подпись)

--bsign-passphrase-file

Путь к файлу с паролем (для пакетного режима)

--bsign-detached

Использовать отделённые подписи (-D)

--bsign-detached-path

Каталог для сохранения отделённых подписей

Логирование#

  • -v, --verbose — подробный вывод;

  • -q, --quiet — минимальный вывод;

  • -l, --log-level — уровень логирования.

Параметры команды analyze#

Параметр

Обязательный

Описание

-p, --package

Да

Имя deb-пакета для анализа

-r, --runtime

Нет

Идентификатор рантайма для сравнения

-R, --runtime-version

Нет

Версия рантайма

-a, --arch

Нет

Архитектура (по умолчанию: amd64)

--recommends

Нет

Включить рекомендуемые пакеты в анализ

--suggests

Нет

Включить предлагаемые пакеты в анализ

Типы источников#

aft-app поддерживает четыре типа источников для получения файлов приложения.

repository (по умолчанию)#

Загрузка deb-пакета из APT-репозитория:

source:
  type: repository
  repository:
    package: myapp
    version: latest
    components:
      - main

Поля:

  • package (обязательное) — имя deb-пакета;

  • version — версия пакета (по умолчанию: latest);

  • components — компоненты репозитория (по умолчанию: ["main"]).

Зависимости анализируются через apt-cache depends.

local#

Использование локального deb-файла:

source:
  type: local
  local:
    path: /path/to/myapp_1.0_amd64.deb

Поля:

  • path (обязательное) — абсолютный путь к .deb-файлу.

Зависимости анализируются из метаданных пакета.

url#

Загрузка deb-пакета по URL:

source:
  type: url
  url:
    address: https://example.com/downloads/myapp_1.0_amd64.deb

Поля:

  • address (обязательное) — URL файла для загрузки.

Анализ зависимостей для этого типа не выполняется.

tar#

Распаковка архива с предварительно подготовленными файлами:

source:
  type: tar
  tar:
    path: /path/to/myapp.tar.xz
    packages:
      - libc6
      - libssl3
    layout:
      - pattern: "*.so*"
        dest: lib/
      - pattern: myapp
        dest: bin/

Поля:

  • path (обязательное) — путь к tar-архиву (.tar.gz или .tar.xz);

  • packages — перечень пакетов для SBOM (анализ зависимостей не выполняется);

  • layout — правила размещения файлов (массив пар pattern/dest).

Правила layout определяют, в какой подкаталог files/ помещаются файлы, соответствующие указанному шаблону (glob). Если layout не указан, содержимое архива распаковывается как есть.

Автономный режим (standalone)#

В автономном режиме приложение включает в себя всю корневую файловую систему (rootfs), а не ссылается на внешний рантайм. Это увеличивает размер пакета, но делает его полностью самодостаточным.

standalone:
  enabled: true
  rootfs: /path/to/rootfs

Принцип работы#

Flatpak требует, чтобы у каждого приложения был рантайм. В автономном режиме aft-app автоматически создаёт фиктивный рантайм и SDK, в которых все каталоги usr/ (bin, lib, share и т. д.) являются символическими ссылками на /app/. Благодаря этому приложение само содержит все необходимые файлы, а рантайм просто делегирует обращения в /app/.

Структура фиктивного рантайма:

usr/
├── bin -> /app/bin
├── lib -> /app/lib
├── lib64 -> /app/lib64
├── share -> /app/share
├── include -> /app/include
├── libexec -> /app/libexec
├── sbin -> /app/sbin
├── etc/                  # реальный каталог (passwd, group, ld.so.conf)
└── .ref                  # маркер Flatpak

Каталог etc/ является реальным (не симлинком) и содержит минимальный набор файлов, необходимых для работы Flatpak: passwd, group и ld.so.conf (копируется из rootfs при наличии).

Именование рантайма#

Секция runtime в манифесте необязательна. Если она не указана, идентификаторы формируются автоматически:

  • Runtime ID: <metadata.id>.Platform (например, org.example.MyApp.Platform)

  • SDK ID: <metadata.id>.Sdk (например, org.example.MyApp.Sdk)

  • Версия: значение metadata.branch или stable

Секцию runtime можно указать явно для задания произвольных имён:

runtime:
  id: org.example.CustomRuntime
  version: "1.0"
  sdk: org.example.CustomSdk

standalone:
  enabled: true
  rootfs: /path/to/rootfs

Импорт rootfs#

Содержимое rootfs/usr/* копируется в files/ приложения (usr/binfiles/bin, usr/libfiles/lib и т. д.). Каталог rootfs/etc копируется в files/etc.

Каталог rootfs должен содержать как минимум структуру usr/ с библиотеками и исполняемыми файлами.

Экспорт#

При экспорте в репозиторий aft-app помещает три объекта:

  1. Само приложение;

  2. Фиктивный рантайм (--runtime);

  3. Фиктивный SDK (--runtime).

Все три объекта попадают в один и тот же OSTree-репозиторий, указанный в секции export.

Предупреждение

Автономные приложения значительно больше по размеру и не используют разделяемые рантаймы. Применяйте этот режим только когда целевая система не имеет совместимого рантайма.

Примеры#

Сборка из манифеста#

sudo aft-app build myapp.yaml

Сборка из командной строки#

sudo aft-app package \
    --id org.example.MyApp \
    --version 1.0.0 \
    --package myapp \
    --runtime org.example.Platform \
    --runtime-version stable \
    --command myapp \
    --socket x11 \
    --socket wayland \
    --socket pulseaudio \
    --device dri \
    --share network \
    --share ipc \
    --output ./repo

Анализ зависимостей#

aft-app analyze --package firefox --runtime org.example.Platform --runtime-version stable

Валидация манифеста#

aft-app validate myapp.yaml

Обработка ошибок#

aft-app использует код возврата 0 при успешном завершении и 1 при любой ошибке. Типичные ошибки:

Отсутствие привилегий:

ОШИБКА: Эта команда требует привилегий суперпользователя
Пожалуйста, запустите программу с помощью sudo:
  sudo aft-app <команда> [опции]

Пакет не найден:

Пакет не найден в репозиториях: <имя-пакета>

Неизвестный тип источника:

Неизвестный тип источника: <тип>
  Допустимые значения: repository, local, url, tar

Ошибка валидации:

Манифест 1 (org.example.MyApp) содержит ошибки:
✗ Ошибки валидации манифеста 1:
  - Идентификатор приложения должен содержать точку
  - Не указана команда запуска

При сборке нескольких манифестов из одного файла ошибка в одном из них не прерывает обработку остальных.