Scripts to build termux-packages for Code on the Go.
Get this Git repository with :
git clone --recurse-submodules https://github.com/appdevforall/terminal-packages.git./build.sh -a aarch64build.sh will patch termux-packages if needed, set up the output directories and then start building the packages. See termux-packages wiki for more information about the build system, patches, build scripts, etc.
The key specified with the -s option is the public key (NOT the private key!), which can be generated using :
gpg --export <key-id> > public-key.gpg
Run build.sh -h to learn more about the available build options.
After the packages have been built, an APT repository can be generated with the following command :
./generate-apt-repo.shThe APT repository will be created in the output/repo directory.
The newly generated repository needs to be signed before it can be published. Sign the repository will the following command :
gpg --default-key <secret-key-id> --yes --pinentry-mode loopback --digest-algo SHA256 --clearsign -o ./output/repo/dists/stable/InRelease ./output/repo/dists/stable/ReleaseWhere <secret-key-id> is the ID of the GPG secret key to be used for signing. Usually, this is the same key you used in step 1. You may be prompted to enter the password for the GPG key.
The repository must be signed after each time it is generated.
After signing, the contents of the output/repo directory can be published to a web hosting service or a S3-compatible storage server. Ensure that the directory structure is same as the repository URL.
For example, if the repository URL is https://packages.appdevforall.org/apt/termux-main, then the contents of the output/repo directory must be stored in the apt/termux-main directory of packages.appdevforall.org's content root (usually, it's something like /www/public/html/packages.appdevforall.org in web hosting environments).
If you have SSH access to the web hosting service, then you can use rsync for incremental updates :
rsync -vrPL ./output/repo/* <user>@<host>:<content-root>/<repository-root>
Where :
<user>is SSH server username.<host>is the SSH server hostname.<content-root>is the root directory of the website.<repository-root>is the directory where the repository should be stored.
From the root directory of this repository, use the following command to generate the bootstrap packages :
./generate-bootstrap-archive.sh
Run the above script with -h to see available options.
The script generates two archives in the output directory :
bootstrap-<variant>-<arch>.zip- bootstrap archive without compression (zip -0). This can be used for generating brotli-compressed archive.bootstrap-<variant>-<arch>.zip.9- this isbootstrap-<arch>.ziparchive compressed with max ZIP compression (zip -9).
The Build packages workflow (.github/workflows/build-packages.yml) builds named packages on GitHub's x86_64 runners. It does not publish them. Run it from Actions → Build packages → Run workflow, or :
gh workflow run build-packages.yml -f packages="jq tree" -f arch=bothpackages- space-separated names fromtermux-packages/packages/.arch-aarch64,arm, orboth(one job per architecture, in parallel).skip_dependencies- build only the named packages (build-package.sh -s). Most packages need at leastlibandroid-support, so leave it off unless the package is known to build without its dependencies.
The builder image is built from the pinned submodule's scripts/Dockerfile, so its NDK and tools match our recipes. Dependencies are built from source on every run.
Each job uploads packages-<arch>.tar with the .deb files and build.log. A job fails if a built package still contains a /data/data/com.termux/ path, unless the package is listed in com-termux-path-exceptions.txt.
Check publish to add the built packages to the apt repository on Cloudflare R2. staging, on by default, publishes to the stage-packages-appdevforall-org bucket; uncheck it to publish to packages-appdevforall-org, which serves packages.appdevforall.org.
publish-apt-repo.sh reads the bucket's current repository and verifies every package against its index. It adds packages that are new or have a higher version, and keeps the published file when the built version is the same or lower. It then regenerates the index with generate-apt-repo.sh and signs InRelease and Release.gpg with the key that matches adfa-dev-team.gpg. It uploads the .deb files before the index and never deletes a file.
The Copy prod packages to stage workflow (.github/workflows/copy-prod-to-stage.yml) makes the stage bucket an exact copy of prod.
Both need the repository variables CLOUDFLARE_ACCOUNT_ID and CLOUDFLARE_KEY_ID, and the secrets CLOUDFLARE_SECRET_ACCESS_KEY (an R2 key that can read and write both buckets), TERMUX_PACKAGE_PRIVATE_GPG_KEY and, if the key has one, TERMUX_PACKAGE_GPG_PASSPHRASE.
Copyright (C) 2025 Akash Yadav
This file is part of The Scribe Project.
Scribe is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Scribe is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Scribe. If not, see <https://www.gnu.org/licenses/>.