Если вы поддерживаете набор утилит, библиотек или внутренних инструментов для Termux, то удобнее централизованно распространять их через APT. Собственный репозиторий дает воспроизводимость сборок, предсказуемые версии и единый канал обновлений.
В этой статье разберем, как автоматизировать:
- сборку пакетов под архитектуры Termux;
- генерацию метаданных APT (Packages/Release);
- подпись репозитория;
- публикацию в виде статического хранилища (например, GitHub Pages) или на отдельный сервер;
- обновление конфигурации на стороне клиента Termux.
Материал ориентирован на «собственные репозитории» и не затрагивает обход ограничений или какие-либо противозаконные сценарии.
Принципиальная схема пайплайна GitHub Actions
Типовой поток выглядит так:
- В репозитории Git хранится исходный код пакета и файлы метаданных (например,
debian/control,debian/changelogили структура сборки под Termux). - GitHub Actions запускает сборку для нужных целей (например,
aarch64,armи т.д.). - Собранные
.debпакеты помещаются в структуру репозитория (включаяpool/и/или директории под архитектуры). - Выполняется индексация APT через
dpkg-scanpackagesи формированиеRelease. - Подписывается репозиторий (GPG) и итоговые файлы публикуются в целевой хостинг.
На выходе пользователь Termux получает URL к вашему репозиторию и может выполнять pkg upgrade / apt update / apt install для нужных пакетов.
Подготовка структуры проекта
Начните с репозитория, который GitHub Actions будет собирать. Практично хранить:
- Исходники (ваш код).
- Файлы сборки (scaffold под Debian/Termux Packaging).
- Скрипты для индексации и публикации.
- Конфиг репозитория (пути, компоненты, архитектуры).
Пример структуры:
repo/
packages/
mytool/
debian/
control
rules
changelog
sources.list
build.sh
scripts/
build_one.sh
repo_index.sh
repo_release.sh
publish.sh
.github/
workflows/
release.yml
В зависимости от того, как именно вы собираете под Termux (через Docker/скрипты, используете готовые тулчейны и т.д.), содержимое build.sh и rules будет различаться. Смысл — четко отделить «сборку пакета» от «формирования APT-индексов» и «публикации».
GitHub Secrets: что нужно для публикации и подписи
Для автоматизации безопасно хранить секреты в GitHub Secrets. Обычно нужны:
GPG_PRIVATE_KEY— приватный ключ для подписи (ASCII-armored или base64 — как решите);GPG_PASSPHRASE— пароль (если ключ защищен);REPO_PUBLISH_TOKEN— токен для загрузки артефактов (например, если вы публикуете на сервер по HTTPS/SSH или в репозиторий страниц);- адрес назначения:
PUBLIC_REPO_URLили путь в артефакт-хранилище.
Примечание: не коммитьте приватный ключ в Git.
Сборка пакетов: базовый подход
Сборка под Termux часто требует специфичной среды (ABI, тулчейн, зависимости). На практике есть два распространенных варианта:
- Сборка внутри контейнера (Docker) с корректным окружением.
- Сборка через установленный тулчейн на runner’е (реже удобнее, чем контейнер).
Ниже пример «скелета» для сборки одного пакета с параметром архитектуры. Адаптируйте под вашу систему сборки:
#!/usr/bin/env bash
set -euo pipefail
PACKAGE_NAME="$1"
ARCH="$2"
echo "Building ${PACKAGE_NAME} for ${ARCH}"
# Пример: запускаем сборку (адаптируйте команды под ваш пакет)
# Можно использовать docker, qemu, или ваш тулчейн.
# Здесь оставим заглушку:
./packages/${PACKAGE_NAME}/build.sh "${ARCH}"
# Ожидаем, что build.sh положит результат в out/
# Например: out/${ARCH}/mytool_1.2.3_${ARCH}.deb
Главное — чтобы по завершении пайплайна у вас были .deb файлы, разложенные по предсказуемому пути.
Формирование APT-индексов (Packages и Release)
APT репозиторий обычно содержит:
dists/<codename>/main/binary-<arch>/Packages.gzdists/<codename>/main/binary-<arch>/Releaseили общийdists/<codename>/Releaseв зависимости от вашей схемы;- файлы с checksums (
MD5Sum,SHA256и т.п.); - подписанные метаданные:
InReleaseилиRelease.gpg.
Скрипт индексации обычно включает:
- генерацию списка пакетов через
dpkg-scanpackages; - сжатие
gzip; - формирование
Releaseи вычисление хэшей.
Пример скрипта индексации (адаптируйте под ваши пути):
#!/usr/bin/env bash
set -euo pipefail
REPO_ROOT="${1:-repo-out}"
DIST_CODENAME="${2:-stable}"
COMPONENT="${3:-main}"
ARCH_LIST=("$@") # Не используйте так в проде; ниже покажем концепт
echo "Indexing repo at ${REPO_ROOT} (dist=${DIST_CODENAME}, component=${COMPONENT})"
# Пример пути, куда вы положили .deb:
# repo-out/
# pool/
# dists/
# stable/
# main/
# binary-aarch64/ (Packages...)
# binary-arm/ (...)
# Допустим, вы храните .deb в pool/:
# pool/mytool_1.2.3_aarch64.deb и т.п.
Практический вариант, более близкий к типичному workflow:
#!/usr/bin/env bash
set -euo pipefail
REPO_OUT="${1:?REPO_OUT is required}"
DIST_CODENAME="${2:-stable}"
COMPONENT="${3:-main}"
# Архитектуры, которые вы собираете
ARCHES=("aarch64" "arm" "i686")
mkdir -p "${REPO_OUT}/dists/${DIST_CODENAME}/${COMPONENT}"
for ARCH in "${ARCHES[@]}"; do
mkdir -p "${REPO_OUT}/dists/${DIST_CODENAME}/${COMPONENT}/binary-${ARCH}"
# dpkg-scanpackages читает .deb в каталоге pool/
# В реальности уточните, где лежат ваши deb-артефакты по архитектурам
dpkg-scanpackages "${REPO_OUT}/pool"
| gzip -9c
> "${REPO_OUT}/dists/${DIST_CODENAME}/${COMPONENT}/binary-${ARCH}/Packages.gz"
done
Далее формируем Release. В простейшем подходе можно использовать apt-ftparchive, если он доступен в вашем окружении. Пример-скелет:
#!/usr/bin/env bash
set -euo pipefail
REPO_OUT="${1:?REPO_OUT is required}"
DIST_CODENAME="${2:-stable}"
COMPONENT="${3:-main}"
# Используйте apt-ftparchive, если доступно
# apt-ftparchive generate /path/to/config > dists/stable/Release
# Ниже — концептуальный пример.
Если apt-ftparchive недоступен, можно собирать Release вручную через шаблоны и утилиты расчета хэшей. Важно: Release должен содержать корректные поля (значения размеров/хэшей), иначе клиенты будут отклонять репозиторий.
Подпись репозитория (GPG) в GitHub Actions
Для корректной работы APT подписывайте Release. Типовая логика:
- Импортировать приватный ключ в
gpgна runner’е; - Сформировать
Release(илиInRelease); - Выполнить подпись.
Пример шага GitHub Actions для импорта ключа:
- name: Import GPG key
run: |
echo "${GPG_PRIVATE_KEY}" > private.key
gpg --batch --import private.key
И пример подписи:
- name: Sign Release
env:
GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }}
run: |
# Предполагаем, что Release уже создан:
# ${REPO_OUT}/dists/stable/Release
gpg --batch --yes --pinentry-mode loopback
--passphrase "${GPG_PASSPHRASE}"
-abs -o "${REPO_OUT}/dists/stable/Release.gpg"
"${REPO_OUT}/dists/stable/Release"
Если вы используете InRelease (clear-signed), то команда и формат будут отличаться. Главное — следить за тем, чтобы клиент Termux ожидал тот тип подписи, который вы публикуете.
Публикация: куда выкладывать repo
Варианты:
- GitHub Pages (удобно для статических файлов): собираете структуру и пушите в ветку/папку для страниц.
- Отдельный web-сервер (Nginx/Apache/S3 compatible): грузите файлы через токен.
- Артефакт в GitHub (для тестов) — но APT обычно требует стабильного URL.
Смысл публикации: чтобы итоговые файлы лежали по URL вида:
https://example.com/your-repo/dists/stable/Release
https://example.com/your-repo/dists/stable/main/binary-aarch64/Packages.gz
Пример workflow GitHub Actions
Ниже пример .github/workflows/release.yml как каркас. Он показывает логику: сборка → индексация → Release → подпись → публикация.
name: Build and Publish Termux APT repo
on:
workflow_dispatch:
push:
tags:
- "v"
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install -y dpkg-dev gzip gnupg
- name: Build packages
env:
DIST_CODENAME: stable
run: |
set -euo pipefail
# Создаем рабочую директорию под репозиторий
REPO_OUT="repo-out"
rm -rf "${REPO_OUT}"
mkdir -p "${REPO_OUT}/pool"
# Пример: собираем один пакет под набор архитектур
# Адаптируйте под ваши пакеты/архитектуры
PACKAGES=("mytool")
ARCHES=("aarch64" "arm")
for PKG in "${PACKAGES[@]}"; do
for ARCH in "${ARCHES[@]}"; do
echo "Building ${PKG} for ${ARCH}"
# Выполняйте вашу сборку: должен появиться .deb
./scripts/build_one.sh "${PKG}" "${ARCH}"
# Пример размещения .deb в pool/
# Ожидаем, что build.sh кладет deb в out/${ARCH}/
# и далее мы копируем:
cp -v "out/${ARCH}/".deb "${REPO_OUT}/pool/"
done
done
- name: Index repo
run: |
set -euo pipefail
./scripts/repo_index.sh "repo-out" "stable" "main"
- name: Create Release file
run: |
set -euo pipefail
# Реализуйте repo_release.sh под вашу структуру:
# должен сформироваться repo-out/dists/stable/Release
./scripts/repo_release.sh "repo-out" "stable" "main"
- name: Import GPG key
run: |
set -euo pipefail
echo "${GPG_PRIVATE_KEY}" > private.key
gpg --batch --import private.key
env:
GPG_PRIVATE_KEY: ${{ secrets.GPG_PRIVATE_KEY }}
- name: Sign Release
run: |
set -euo pipefail
gpg --batch --yes --pinentry-mode loopback
--passphrase "${GPG_PASSPHRASE}"
-abs -o "repo-out/dists/stable/Release.gpg"
"repo-out/dists/stable/Release"
env:
GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }}
- name: Publish
run: |
set -euo pipefail
# Реализуйте publish.sh: например, пуш в gh-pages
./scripts/publish.sh "repo-out"
env:
REPO_PUBLISH_TOKEN: ${{ secrets.REPO_PUBLISH_TOKEN }}
PUBLIC_REPO_URL: ${{ secrets.PUBLIC_REPO_URL }}
Даже если вы используете другой способ публикации, структура workflow не меняется: ключевые точки — артефакты, индексация, Release/подпись, публикация.
Подключение репозитория на стороне Termux
На устройстве в Termux добавьте ваш источник. Обычно редактируют файл репозиториев (в зависимости от версии Termux/apt):
- обновление списка источников;
- проверка, что APT видит Packages;
- установка нужных пакетов.
Пример команд (адаптируйте под вашу конкретную версию и путь репозитория):
termux-change-repo
Если вы вручную добавляете строку источника, она обычно имеет вид:
deb https://example.com/your-repo stable main
Дальше:
pkg update
pkg upgrade
pkg install mytool
Если вы используете подпись Release, убедитесь, что клиентская система может проверить ключ. На стороне Termux обычно импортируют ключ (в зависимости от настроек APT). Практика: приложить открытый ключ в репозитории (например, repo.gpg) и документировать его для пользователей.
Тестирование и контроль качества
Чтобы избежать неприятных сюрпризов после публикации:
- Включайте «проверку артефактов» перед публикацией: наличие
.deb, корректность путей, наличиеPackages.gzиRelease. - Проверяйте, что
Release.gpgформируется успешно и соответствует вашему ключу. - Добавляйте отдельный stage для smoke-test: скачайте
Packages.gzи убедитесь, что в индексе присутствуют ожидаемые пакеты.
Пример проверки целостности (концепт):
ls -la repo-out/dists/stable/main/binary-aarch64/Packages.gz
ls -la repo-out/dists/stable/Release
ls -la repo-out/dists/stable/Release.gpg
Распространенные ошибки
- Неправильные пути в dists/: APT жестко ожидает структуру. Согласуйте
binary-ARCH,componentиcodename. - Отсутствие Packages.gz для архитектуры: клиент не сможет найти пакеты.
- Release не соответствует Packages: несостыковка хэшей/размеров приводит к ошибкам проверки.
- Сломанная подпись: неверный ключ или неподдерживаемый формат подписи.
Безопасность и эксплуатация
Для безопасной эксплуатации:
- Минимизируйте доступ к секретам: выдавайте токены только на нужные операции.
- Ограничьте публикацию: делайте публикацию только по тегам/релизам или вручную.
- Логируйте шаги, но не выводите секреты.
Если вам необходимо использовать VPN, то только для создания локальной сети для разработки/доступа к внутренним ресурсам (например, приватный репозиторий или build-host). Не используйте VPN для обхода блокировок.
Заключение
Автоматизация сборки и публикации собственных APT-репозиториев для Termux с GitHub Actions — это практичный способ поддерживать набор пакетов в актуальном состоянии, ускорить релизы и сделать обновления предсказуемыми для пользователей. Ключевые элементы решения: воспроизводимая сборка .deb, генерация Packages.gz, корректный Release, подпись GPG и стабильная публикация по URL.
Если вы хотите спроектировать пайплайн под ваши пакеты, настроить структуру dists/, подпись и публикацию, а также провести аудит сборочных скриптов — обращайтесь в РыбинскЛАБ. Мы поможем довести процесс до надежного промышленного уровня.