Custom Arch Linux Repository
This article is heavily influenced by these existing articles.
- https://www.sainnhe.dev/post/create-personal-arch-linux-package-repository/
- https://wiki.archlinux.org/title/pacman/Tips_and_tricks#Custom_local_repository
The goal here is to create a static hosted website that can act as a repository for use with Arch Linux. For this purpose I primaily use two scripts.
generate-key.sh
is a bash script used to generate a
GPG key for the sake of signing my packages.
#!/usr/bin/env bash
set -e
script_dir=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
if gpg --export --armor -a "MY NAME (Archlinux Private Package Repo)" |& grep 'gpg: WARNING: nothing exported'
then
gpg --pinentry-mode=loopback --batch --gen-key --passphrase '' <<EOF
Key-Type: 1
Key-Length: 2048
Subkey-Type: 1
Subkey-Length: 2048
Name-Real: MY NAME (Archlinux Private Package Repo)
Name-Email: MY_USERNAME@users.noreply.github.com
Expire-Date: 0
EOF
fi
gpg --armor --export "MY NAME (Archlinux Private Package Repo)" > "./my-repository-key.gpg"
build.sh
is a bash script used to walk a directory of
packages and build them all automatically. Note
PKGDEST
would publish all the packages to
./docs
, which is helpful when publishing to GitHub
Pages. This path can be changed.
#!/usr/bin/env bash
set -e
script_dir=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
# Update this as needed
gpg --import "${HOME}/my-repository-key.gpg"
# tail -1 to get the subkey, which is what ends up used for signing
key_id="$(gpg --list-keys --with-colons 'MY NAME' | awk -F: '$1=="fpr" { print $10 }' | tail -1)"
# Publish the
export PKGDEST="${script_dir}/docs"
export GPGKEY="${key_id}"
export PACKAGER="MY NAME <MY_USERNAME@users.noreply.github.com>"
rm -f "${PKGDEST}/my-repository.db.tar.gz"
rm -f "${PKGDEST}/my-repository.files.tar.gz"
find "${PKGDEST}" -type f -name "*.sig" -delete
# Iterate over package directories prefixed by 'my-package-'
for package_path in "${script_dir}"/my-package-*
do
namcap "${package_path}/PKGBUILD"
package_name="$(basename "${package_path}")"
echo "${package_name} ${package_path}"
# Use yay for aur resolutions? https://www.reddit.com/r/archlinux/comments/jj15c5/comment/gaanf7x/?context=3
# --nodeps for meta/virtual packages with no real build steps.
pushd "${package_path}"
makepkg -f --nodeps --sign
popd
package_output_path="$(ls "${PKGDEST}/${package_name}"*.pkg.tar.zst)"
namcap "${package_output_path}" | grep 'E:' || true
done
repo-add --key "${key_id}" --verify --sign "${PKGDEST}/my-repository.db.tar.gz" "${PKGDEST}/"*.pkg.tar.zst
Supporting files, helper scripts, and other data can also be copied to the output directory as needed. Be careful not to accidentally publish any sensitive scripts or information
The client can be configured like so. See here for an entry that
could be added to /etc/pacman.conf
.
[my-repository]
Server = https://my-repository.my-domain.com
Use --overwrite
to indicate that we are explicitly
overriding a system config file if necessary.
pacman --overwrite "*" -Syy <the package>