You are not logged in.
Hello,
I have created packages for my personal use for maybe two years now but never submitted them to the AUR. Now I would like to submit two of them (not yet submitted). I've got permission from the developer of Psono to add his software to the AUR under the condition that it needs to include a disclaimer that the package is not officially supported and the developer is not responsible for any issues with it. I've read the Arch Linux package guidelines cover to cover and also made both packages REUSE compliant. Both PKGBUILD files are almost identical (apart from the software edition) so i will show only one here. The PKGBUILD downloads a docker image from docker hub and extracts the needed files from it for use. The docker fetch function was downloaded from GitHub. This is mentioned and linked in a commented out line in the PKGBUILD. I do have a few questions regarding the Python environment it uses at the bottom of the post.
Contents of PKGBUILD:
# Maintainer: 7thCore <redacted-for-now>
# Disclaimer: This AUR package is maintained by the community and is not
# officially supported by the software developers or the package maintainer.
# Use this package at your own risk. The developers of the original software
# and the package maintainer are not responsible for any issues, bugs, or
# damages resulting from its use. For installation or usage questions, please
# do not contact the original developers. Instead, seek assistance from the
# package maintainer, the Arch Linux community or relevant forums.
pkgname=psono-ee-combo
pkgver=1.0
pkgrel=1
pkgdesc='Enterprise Edition of the open source and self hosted password manager. Includes the server, file server, web client and web admin portal.'
arch=('x86_64' 'aarch64')
url='https://psono.com'
license=('Apache-2.0')
depends=('bash'
'coreutils'
'gcc'
'git'
'glibc'
'haveged'
'libb2'
'libffi'
'libldap'
'libpqxx'
'libsasl'
'libyaml'
'nginx'
'openssl'
'postgresql'
'python>=3.14'
'util-linux')
optdepends=('logrotate: rotates system logs automatically'
'fail2ban: bans IPs after too many failed authentication attempts')
makedepends=('curl'
'gzip'
'jq'
'patchelf'
'sed'
'tar')
provides=('psono-server'
'psono-fileserver'
'psono-web-client'
'psono-admin-client')
conflicts=('psono-server'
'psono-fileserver'
'psono-web-client'
'psono-admin-client')
backup=('etc/fail2ban/filter.d/psono-ee.conf'
'etc/fail2ban/jail.d/psono-ee.local'
'etc/logrotate.d/psono'
'etc/nginx/sites-available/psono-ee-combo.conf'
'usr/share/webapps/psono-webclient/config.json'
'usr/share/webapps/psono-webclient/portal/config.json'
'var/lib/psono/.psono_fileserver/settings.yaml'
'var/lib/psono/.psono_server/settings.yaml')
options=('!strip' '!debug')
install='psono-script.install'
source=('conf_psono.logrotate'
'conf_psono-fail2ban-filter.conf'
'conf_psono-fail2ban-jail.local'
'conf_psono-fileserver-settings.yaml'
'conf_psono-nginx.conf'
'conf_psono-server-settings.yaml'
'pacman_05-psono-ee-pre.hook'
'pacman_99-psono-ee-post.hook'
'psono-ee-server-requirements.patch'
'psono-script.install'
'psono-ee-combo.sysusers'
'script_psono-ee-pacman-hooks.sh'
'systemd_psono-fileserver-cleanup.service'
'systemd_psono-fileserver-cleanup.timer'
'systemd_psono-fileserver-ping.service'
'systemd_psono-fileserver-ping.timer'
'systemd_psono-fileserver.service'
'systemd_psono-server-ee-cleartoken.service'
'systemd_psono-server-ee-cleartoken.timer'
'systemd_psono-server-ee.service')
sha256sums=('bd391b1824d182c3d5813ca71535d5e47c2404883f1bc58f76b677fde3d6e70f'
'66ac600efad0aa1af7ddfeca5452f369ac3fe8f0e8c9ad90ae1bf73be18460bc'
'5d422995f77d17c65d7827e0af27afb0ba6500e91e17f66fcb758aa322d8108c'
'7d658724229b49a4e69e45e0a57b536a42ec02ad1c3343539b21f8fa505c1002'
'2f815769b7dd5c672b491138e59e1709ea30676d66c7562ad54c7c2ce14dc55c'
'6316939b8c5a36b1b3c379a50d5a86a2d4c153a4e38ec7b2b2e18da7ad7db34d'
'b3cdc9d315b628f0970459a4af08bbe4b5c08e1b8a0dff8da7f5a0c6875c76f9'
'd9f9810503879afd9774e399d1efe6d1f3dfe3aaa017f0ce16010ff8549a858d'
'4a171e8c0ee529bad90ad37e6633f8dc7cfe40e02fb4cf24f6e95f8084b4584a'
'1077a9ba4f0412a9cc1307a5783a5fcb9d1f8ae189c4bab88f36ef7c42010a31'
'a38ec954b0d09883de180bc08205c63c09399e2c62736b0c5e9b49f672ddadc8'
'42bc0970dc2b9918191893d08b32cb94d643e5bbb6c791f4a0d0ad7d70c8a153'
'af7985b5a1ebf8664888959f8dd9f4d24ada00702548e4e07253eacddacc8403'
'ac7d656c02632ca81fb3683a65764b076e25a5ae39bdd2a4ef9d5827b984e1fe'
'4009d186b42e1c79bebf340899a649a15f2019945dca1d81bcd8ec9455852e97'
'e013719b0a8fd62e4c1d0fc3e83fc1903fc7189205bb58899b7e5fd4a7ae6b26'
'36f51e9ae755436353caebf80bda3293122729a26a3cc75ff6b652a2460c9977'
'108d1cf9373cc5ebb98373b3469a64a24e6fd4bfc973e0056d2101b6c77de442'
'ebc9d9ad66ff7cfdbf4698b2ce24392b1a52ff6a0294f72288e14be1ede6219b'
'7f8252a5fc9967e5f373688039fa2136ab914ed94d2e8d514eadc817a5b708ff')
pkgver() {
# The version number is combined by the developer on docker. First numbers are the server version,
# second are the client portal version and third are the admin portal version. To keep up with this
# version form, add the file server version to the version number.
PSONO_EE_COMBO_VERSION=$(curl -s "https://hub.docker.com/v2/repositories/psono/psono-combo-enterprise/tags?page_size=1" | jq -r '.results[0].name' | sed 's/-/_/g')
PSONO_FILESERVER_VERSION=$(curl -s "https://hub.docker.com/v2/repositories/psono/psono-fileserver/tags?page_size=1" | jq -r '.results[0].name')
printf "$PSONO_EE_COMBO_VERSION"_"$PSONO_FILESERVER_VERSION"
}
prepare() {
# Docker fetch function modified from https://github.com/jjlin/docker-image-extract
docker_fetch() {
PLATFORM="$2"
OUT_DIR="${srcdir}/psono-src-docker"
image_spec="$1"
image="${image_spec%%:*}"
if [ "${image#*/}" = "${image}" ]; then
image="library/${image}"
fi
ref="${image_spec#*:}"
# Split platform (OS/arch/variant) into separate variables.
IFS=/ read -r OS ARCH VARIANT <<< "${PLATFORM}"
fetch() {
if [ $# -eq 2 ]; then
set -- -H "$2" "$1"
elif [ $# -eq 3 ]; then
set -- -H "$2" -H "$3" "$1"
fi
curl -sSL "$@"
}
manifest_list_url="https://hub.docker.com/v2/repositories/${image}/tags/${ref}"
if [ -z "${ref##sha256:*}" ]; then
digest="${ref}"
else
echo "Getting multi-arch manifest list..."
digest=$(fetch "${manifest_list_url}" | jq -r '.images[] | select(.architecture == "'"${ARCH}"'" and .os == "'"${OS}"'" and (.variant == "'"${VARIANT}"'" or (.variant | not))) | .digest' | head -n 1)
if [ -n "${digest}" ]; then
echo "Platform ${PLATFORM} resolved to '${digest}'..."
else
echo "No image digest found. Verify that the image, ref, and platform are valid."
exit 1
fi
fi
api_token_url="https://auth.docker.io/token?service=registry.docker.io&scope=repository:$image:pull"
manifest_url="https://registry-1.docker.io/v2/${image}/manifests/${digest}"
blobs_base_url="https://registry-1.docker.io/v2/${image}/blobs"
echo "Getting API token..."
token=$(fetch "${api_token_url}" | jq -r '.token')
auth_header="Authorization: Bearer $token"
docker_manifest_v2="application/vnd.docker.distribution.manifest.v2+json"
oci_manifest_v1="application/vnd.oci.image.manifest.v1+json"
accept_header="Accept: ${docker_manifest_v2},${oci_manifest_v1}"
echo "Getting image manifest for $image:$ref..."
layers=$(fetch "${manifest_url}" "${auth_header}" "${accept_header}" | jq -r '.layers[].digest')
if [ -z "${layers}" ]; then
echo "No layers returned. Verify that the image and ref are valid."
exit 1
fi
for layer in $layers; do
hash="${layer#sha256:}"
echo "Fetching and extracting layer ${hash}..."
fetch "${blobs_base_url}/${layer}" "${auth_header}" | gzip -d | tar -C "${OUT_DIR}" -xf -
OLD_IFS="${IFS}"
find "${OUT_DIR}" -name '.wh.*' | while IFS= read -r f; do
dir="${f%/*}"
wh_file="${f##*/}"
file="${wh_file#.wh.}"
rm -rf "${dir}/${wh_file}" "${dir}/${file}"
done
IFS="${OLD_IFS}"
done
echo "Image contents extracted into ${OUT_DIR}."
}
printf 'Disclaimer: This AUR package is maintained by the community and is not'
printf 'officially supported by the software developers or the package maintainer.'
printf 'Use this package at your own risk. The developers of the original software'
printf 'and the package maintainer are not responsible for any issues, bugs, or'
printf 'damages resulting from its use. For installation or usage questions, please'
printf 'do not contact the original developers. Instead, seek assistance from the'
printf 'package maintainer, the Arch Linux community or relevant forums.'
if [ "$(uname -m)" = "x86_64" ]; then
PLATFORM_DEFAULT="linux/amd64"
elif [ "$(uname -m)" = "aarch64" ]; then
PLATFORM_DEFAULT="linux/arm64"
fi
[ -d "${srcdir}/psono-ee-src" ] && rm -rf "${srcdir}/psono-ee-src"
[ -d "${srcdir}/psono-fs-src" ] && rm -rf "${srcdir}/psono-fs-src"
[ -d "${srcdir}/psono-web" ] && rm -rf "${srcdir}/psono-web"
[ -d "${srcdir}/psono-web-admin" ] && rm -rf "${srcdir}/psono-web-admin"
[ -d "${srcdir}/psono-src-docker" ] && rm -rf "${srcdir}/psono-src-docker"
[ -d "${srcdir}/python_env" ] && rm -rf "${srcdir}/python_env"
mkdir -p "${srcdir}/psono-ee-src"
mkdir -p "${srcdir}/psono-fs-src"
mkdir -p "${srcdir}/psono-web"
mkdir -p "${srcdir}/psono-web-admin"
mkdir -p "${srcdir}/psono-src-docker"
mkdir -p "${srcdir}/python_env"
printf "Fetching Psono Server Enterprise Edition Docker image"
docker_fetch psono/psono-combo-enterprise:latest "$PLATFORM_DEFAULT"
printf "Extracting Psono Server Enterprise Edition from Docker image"
mv ${srcdir}/psono-src-docker/root/psono/* ${srcdir}/psono-ee-src/
mv ${srcdir}/psono-src-docker/root/requirements.txt ${srcdir}/psono-ee-src/
mv ${srcdir}/psono-src-docker/root/requirements-amd64.txt ${srcdir}/psono-ee-src/
mv ${srcdir}/psono-src-docker/root/.pip/pip.conf ${srcdir}/conf_psono-python-pip.conf
printf "Extracting Psono Admin Portal from Docker image"
mv ${srcdir}/psono-src-docker/usr/share/nginx/html/portal/* "${srcdir}/psono-web-admin/"
printf "Extracting Psono Web Portal from Docker image"
mv ${srcdir}/psono-src-docker/usr/share/nginx/html/* "${srcdir}/psono-web/"
printf "Removing unused files of Psono Server Enterprise Edition Docker image"
rm -rf ${srcdir}/psono-src-docker/*
printf "Fetching Psono File Server Docker image"
docker_fetch psono/psono-fileserver:latest "$PLATFORM_DEFAULT"
printf "Extracting Psono File Server from Docker image"
mv ${srcdir}/psono-src-docker/root/psono/* ${srcdir}/psono-fs-src/
mv ${srcdir}/psono-src-docker/root/requirements.txt ${srcdir}/psono-fs-src/
printf "Removing unused files of Psono File Server Docker image"
rm -rf ${srcdir}/psono-src-docker/*
printf "Patching Psono Server Enterprise Edition requirements.txt"
cd "${srcdir}/psono-ee-src" || exit 1
patch -Np1 -i "${srcdir}/psono-ee-server-requirements.patch"
# Find the latest pyarmor_runtime.so folder, cd to it and patch pyarmor_runtime.so
printf "Patching pyarmor_runtime.so ELF by replacing libc.so with libc.so.6 to avoid 'invalid ELF header' errors"
cd "${srcdir}/psono-ee-src" || exit 1
PYARMOR_RUNTIME_DIR=$(ls -d pyarmor_runtime_* | sort -V | tail -n 1)
if [[ -d "$PYARMOR_RUNTIME_DIR" ]]; then
cd "$PYARMOR_RUNTIME_DIR" || exit 1
patchelf --replace-needed libc.so libc.so.6 pyarmor_runtime.so
fi
}
build() {
printf "Preparing Psono Server Enterprise Edition python virtual environment"
/usr/bin/python3.14 -m venv ${srcdir}/python_env/psono-server-ee-3.14
PIP_CONFIG_FILE="${srcdir}/conf_psono-python-pip.conf" ${srcdir}/python_env/psono-server-ee-3.14/bin/python3.14 -m pip install --upgrade pip
PIP_CONFIG_FILE="${srcdir}/conf_psono-python-pip.conf" ${srcdir}/python_env/psono-server-ee-3.14/bin/pip3.14 install -r ${srcdir}/psono-ee-src/requirements.txt
if [ "$(uname -m)" = "x86_64" ]; then
PIP_CONFIG_FILE="${srcdir}/conf_psono-python-pip.conf" ${srcdir}/python_env/psono-server-ee-3.14/bin/pip3.14 install -r ${srcdir}/psono-ee-src/requirements-amd64.txt
fi
PIP_CONFIG_FILE="${srcdir}/conf_psono-python-pip.conf" ${srcdir}/python_env/psono-server-ee-3.14/bin/pip3.14 install gunicorn
printf "Changing paths of python virtual environment files"
find ${srcdir}/python_env/psono-server-ee-3.14 -type f ! -type l -exec sed -i "s|${srcdir}/python_env/psono-server-ee-3.14|/var/lib/psono/.python_env/psono-server-ee-3.14|g" {} +
printf "Deleting python virtual environment cache files"
find ${srcdir}/python_env/psono-server-ee-3.14/lib/python3.14/site-packages -type f -name "*.pyc" -delete -o -type d -name "__pycache__" -exec rm -rf {} +
printf "Preparing Psono File Server python virtual environment"
/usr/bin/python3.14 -m venv ${srcdir}/python_env/psono-fileserver-3.14
PIP_CONFIG_FILE="${srcdir}/conf_psono-python-pip.conf" ${srcdir}/python_env/psono-fileserver-3.14/bin/python3.14 -m pip install --upgrade pip
PIP_CONFIG_FILE="${srcdir}/conf_psono-python-pip.conf" ${srcdir}/python_env/psono-fileserver-3.14/bin/pip3.14 install -r ${srcdir}/psono-fs-src/requirements.txt
PIP_CONFIG_FILE="${srcdir}/conf_psono-python-pip.conf" ${srcdir}/python_env/psono-fileserver-3.14/bin/pip3.14 install gunicorn
printf "Changing paths of python virtual environment files"
find ${srcdir}/python_env/psono-fileserver-3.14 -type f ! -type l -exec sed -i "s|${srcdir}/python_env/psono-fileserver-3.14|/var/lib/psono/.python_env/psono-fileserver-3.14|g" {} +
printf "Deleting python virtual environment cache files"
find ${srcdir}/python_env/psono-fileserver-3.14/lib/python3.14/site-packages -type f -name "*.pyc" -delete -o -type d -name "__pycache__" -exec rm -rf {} +
}
package() {
# Fail2ban
install -dm755 "${pkgdir}/etc/fail2ban/jail.d"
install -dm755 "${pkgdir}/etc/fail2ban/filter.d"
install -Dm644 "${srcdir}/conf_psono-fail2ban-filter.conf" "${pkgdir}/etc/fail2ban/filter.d/psono-ee.conf"
install -Dm644 "${srcdir}/conf_psono-fail2ban-jail.local" "${pkgdir}/etc/fail2ban/jail.d/psono-ee.local"
# Logrotate
install -dm755 "${pkgdir}/etc/logrotate.d"
install -Dm644 "${srcdir}/conf_psono.logrotate" "${pkgdir}/etc/logrotate.d/psono"
# Nginx
install -dm755 "${pkgdir}/etc/nginx/sites-available"
install -dm755 "${pkgdir}/etc/nginx/sites-enabled"
install -Dm644 "${srcdir}/conf_psono-nginx.conf" "${pkgdir}/etc/nginx/sites-available/psono-ee-combo.conf"
# Pacman
install -Dm644 "${srcdir}/pacman_05-psono-ee-pre.hook" "${pkgdir}/usr/share/libalpm/hooks/05-psono-ee-pre.hook"
install -Dm644 "${srcdir}/pacman_99-psono-ee-post.hook" "${pkgdir}/usr/share/libalpm/hooks/99-psono-ee-post.hook"
install -Dm755 "${srcdir}/script_psono-ee-pacman-hooks.sh" "${pkgdir}/usr/share/libalpm/scripts/psono-ee-pacman-hooks.sh"
# Psono
install -dm755 "${pkgdir}/var/lib/psono/psono-fileserver"
install -dm755 "${pkgdir}/var/lib/psono/psono-server-ee"
install -dm755 "${pkgdir}/var/lib/psono/psono-shard"
install -dm755 "${pkgdir}/var/lib/psono/.pip"
install -dm755 "${pkgdir}/var/lib/psono/.psono_fileserver"
install -dm755 "${pkgdir}/var/lib/psono/.psono_server"
install -dm755 "${pkgdir}/var/log/psono"
install -dm755 "${pkgdir}/usr/share/webapps/psono-webclient/portal"
install -Dm644 "${srcdir}/conf_psono-fileserver-settings.yaml" "${pkgdir}/var/lib/psono/.psono_fileserver/settings.yaml"
install -Dm644 "${srcdir}/conf_psono-python-pip.conf" "${pkgdir}/var/lib/psono/.pip/pip.conf"
install -Dm644 "${srcdir}/conf_psono-server-settings.yaml" "${pkgdir}/var/lib/psono/.psono_server/settings.yaml"
install -Dm644 "${srcdir}/psono-ee-combo.sysusers" "${pkgdir}/usr/lib/sysusers.d/psono.conf"
install -Dm644 "${srcdir}/systemd_psono-fileserver-cleanup.service" "${pkgdir}/usr/lib/systemd/system/psono-fileserver-cleanup.service"
install -Dm644 "${srcdir}/systemd_psono-fileserver-cleanup.timer" "${pkgdir}/usr/lib/systemd/system/psono-fileserver-cleanup.timer"
install -Dm644 "${srcdir}/systemd_psono-fileserver-ping.service" "${pkgdir}/usr/lib/systemd/system/psono-fileserver-ping.service"
install -Dm644 "${srcdir}/systemd_psono-fileserver-ping.timer" "${pkgdir}/usr/lib/systemd/system/psono-fileserver-ping.timer"
install -Dm644 "${srcdir}/systemd_psono-fileserver.service" "${pkgdir}/usr/lib/systemd/system/psono-fileserver.service"
install -Dm644 "${srcdir}/systemd_psono-server-ee-cleartoken.service" "${pkgdir}/usr/lib/systemd/system/psono-server-ee-cleartoken.service"
install -Dm644 "${srcdir}/systemd_psono-server-ee-cleartoken.timer" "${pkgdir}/usr/lib/systemd/system/psono-server-ee-cleartoken.timer"
install -Dm644 "${srcdir}/systemd_psono-server-ee.service" "${pkgdir}/usr/lib/systemd/system/psono-server-ee.service"
cp -dr --no-preserve=ownership "${srcdir}/psono-ee-src"/* "${pkgdir}/var/lib/psono/psono-server-ee/"
cp -dr --no-preserve=ownership "${srcdir}/psono-fs-src"/* "${pkgdir}/var/lib/psono/psono-fileserver/"
cp -dr --no-preserve=ownership "${srcdir}/psono-web"/* "${pkgdir}/usr/share/webapps/psono-webclient/"
cp -dr --no-preserve=ownership "${srcdir}/psono-web-admin"/* "${pkgdir}/usr/share/webapps/psono-webclient/portal/"
cp -dr --no-preserve=ownership "${srcdir}/python_env" "${pkgdir}/var/lib/psono/.python_env"
}Source files (I added prefixes for easy managment):
LICENSES
LICENSE
PKGBUILD
README.md
REUSE.toml
conf_psono-fail2ban-filter.conf
conf_psono-fail2ban-jail.local
conf_psono-fileserver-settings.yaml
conf_psono-nginx.conf
conf_psono-server-settings.yaml
conf_psono.logrotate
pacman_05-psono-ee-pre.hook
pacman_99-psono-ee-post.hook
psono-ee-server-requirements.patch
psono-script.install
script_psono-ee-pacman-hooks.sh
systemd_psono-fileserver-cleanup.service
systemd_psono-fileserver-cleanup.timer
systemd_psono-fileserver-ping.service
systemd_psono-fileserver-ping.timer
systemd_psono-fileserver.service
systemd_psono-server-ee-cleartoken.service
systemd_psono-server-ee-cleartoken.timer
systemd_psono-server-ee.serviceREUSE.toml:
version = 1
[[annotations]]
path = [
"PKGBUILD",
"README.md",
"keys/**",
".SRCINFO",
".gitignore",
".nvchecker.toml",
"*.install",
"*.sysusers",
"*sysusers.conf",
"*.tmpfiles",
"*tmpfiles.conf",
"*.logrotate",
"*.pam",
"*.service",
"*.socket",
"*.timer",
"*.desktop",
"*.hook",
"conf_psono-fail2ban-filter.conf",
"conf_psono-fail2ban-jail.local",
"conf_psono-nginx.conf",
"psono-ee-server-requirements.patch",
"script_psono-ee-pacman-hooks.sh",
]
SPDX-FileCopyrightText = "Arch Linux contributors"
SPDX-License-Identifier = "0BSD"
[[annotations]]
path = [
"conf_psono-fileserver-settings.yaml",
"conf_psono-server-settings.yaml",
]
SPDX-FileCopyrightText = "psono-ee-combo contributors"
SPDX-License-Identifier = "Apache-2.0"psono-script.install
post_install() {
printf 'Disclaimer: This AUR package is maintained by the community and is not'
printf 'officially supported by the software developers or the package maintainer.'
printf 'Use this package at your own risk. The developers of the original software'
printf 'and the package maintainer are not responsible for any issues, bugs, or'
printf 'damages resulting from its use. For installation or usage questions, please'
printf 'do not contact the original developers. Instead, seek assistance from the'
printf 'package maintainer, the Arch Linux community or relevant forums.'
printf "Don't forget to setup your Psono configuration and execute the following command to complete the Psono installation before starting the services:"
printf "'runuser -l psono -s /bin/bash -c \"/var/lib/psono/.python_env/psono-server-ee-3.14/bin/python3.14 /var/lib/psono/psono-server-ee/psono/manage.py migrate\"'"
chown -R psono:psono /var/lib/psono
chown -R psono:psono /var/log/psono
}
post_upgrade() {
printf 'Disclaimer: This AUR package is maintained by the community and is not'
printf 'officially supported by the software developers or the package maintainer.'
printf 'Use this package at your own risk. The developers of the original software'
printf 'and the package maintainer are not responsible for any issues, bugs, or'
printf 'damages resulting from its use. For installation or usage questions, please'
printf 'do not contact the original developers. Instead, seek assistance from the'
printf 'package maintainer, the Arch Linux community or relevant forums.'
chown -R psono:psono /var/lib/psono
chown -R psono:psono /var/log/psono
}
pre_remove() {
printf "Backing up Psono configuration and shards to /opt/backups/psono-backup"
mkdir -p /opt/backups/psono-backup
cp /etc/nginx/sites-available/psono-ee-combo.conf /opt/backups/psono-backup/psono-ee-combo-nginx.conf
cp /var/lib/psono/.psono_server/settings.yaml /opt/backups/psono-backup/server_settings.yaml
cp /var/lib/psono/.psono_fileserver/settings.yaml /opt/backups/psono-backup/fileserver_settings.yaml
cp -rf /var/lib/psono/psono-shard /opt/backups/psono-backup/
}
post_remove() {
userdel --remove psono
rm /etc/nginx/sites-available/psono-ee-combo.conf
rm /etc/nginx/sites-enabled/psono-ee-combo.conf
rm -rf /usr/share/webapps/psono-webclient
}script_psono-ee-pacman-hooks.sh
#!/bin/sh
#Stop all psono services
psono_stop() {
/usr/bin/systemctl stop psono-server-ee.service psono-server-ee-cleartoken.timer psono-fileserver.service psono-fileserver-cleanup.timer psono-fileserver-ping.timer
}
#Execute migration and start psono services
psono_migrate_start() {
cd "/var/lib/psono/psono-server-ee" || exit
sudo -u psono /var/lib/psono/.python_env/psono-server-ee-3.14/bin/python3.14 /var/lib/psono/psono-server-ee/manage.py migrate
# The hook runs after 30-systemd-daemon-reload.hook so another systemctl daemon-reload is not necessary.
/usr/bin/systemctl start psono-server-ee.service psono-server-ee-cleartoken.timer psono-fileserver.service psono-fileserver-cleanup.timer psono-fileserver-ping.timer
}
case "$1" in
stop)
psono_stop
;;
migrate)
psono_migrate_start
;;
*)
exit 1
;;
esacQuestions:
- the original software requires a python environment, currently it's being installed by the package install script. The install script however uses sudo and I'm not sure what are the guidelines regarding it so if someone could explain, I'd apprechiate it See Edit 2 below
- are there any other ways python environments are installed with packages? See Edit 6 below
- problem with the libc.so library, apparently it contains "links" to libc.so.6 and is causing problems with python, resulting in "Invalid ELF header" errors. This has been the case for about a year and a half now. Creating a backup of libc.so and symlinking libc.so.6 to libc.so fixes the issue and I created a pacman hook for this process. However from my common sense perspective this is a big no no because libc.so is not part of my package and I shouldn't manipulate it. Am i wrong? Any recommendations? See Edit 4 below
- any other issues i am missing regarding my source files?
Feedback apprechiated.
Regards,
7thCore
Edit: Added url to PKGBUILD and renamed some config files.
Edit 2: Removed sudo as dependancy and replaced sudo with runuser.
Edit 3: Changed the pre_remove() backup location to /opt/backups/psono-backup
Edit 4: Removed pacman libc.so patching and added patchelf to build process to replace libc.so with libc.so.6 in pyarmor_runtime.so ELF in the Psono software to solve the glibc package tampering. Tested in live environment and confirmed working.
Edit 5: Removed checks for curl and wget from docker_fetch(), recoded docker_fetch() to only use curl and jq, removed wget as make dependancy
Edit 6: Added build() function to handle python venv building and packaging with the package, added sysusers file and removed user creation from the install file, removed printf ascii escape codes for color
Last edited by 7thCore (Today 05:46:47)
The Linux philosophy is 'Laugh in the face of danger'. Oops. Wrong One. 'Do it yourself'. Yes, that's it.
Offline
- the original software requires a python environment, currently it's being installed by the package install script. The install script however uses sudo and I'm not sure what are the guidelines regarding it so if someone could explain, I'd apprechiate it
- are there any other ways python environments are installed with packages?
- problem with the libc.so library, apparently it contains "links" to libc.so.6 and is causing problems with python, resulting in "Invalid ELF header" errors. This has been the case for about a year and a half now. Creating a backup of libc.so and symlinking libc.so.6 to libc.so fixes the issue and I created a pacman hook for this process. However from my common sense perspective this is a big no no because libc.so is not part of my package and I shouldn't manipulate it. Am i wrong? Any recommendations?
That suggests the sw needs a specific python setup and relies on libraries provided by them instead of system libraries .I guess this is proprietary software ?
the url= link indicates it's open source.
psono-script.install looks like it's intended to be run as user with elevated rights for certain parts .
Such scripts are not suitable for packages and are only useful to see what things need to be done.
pip is only useful for user environments and is blocked from systemwide stuff, updating systemwide packages is the job of pacman.
To package this software for archlinux you'd probably have to disable the auto-update feature and create packages for psono-server-ee and psono-fileserver .
The pre_remove() function makes changes to /root/ user settings and archlinux packages are forbidden to touch user stuff .
The services and timer files should not be included in the packages, but put somewhere in a vcs (git) repository so they can be maintained and updated when needed.
It might be possible to use a custom DL-agent for the docker part.
I didn't investigate in-depth, but sofar I haven't seen anything that blocks creating archlinux packages for this.
NOTE: it won't be easy, a lot of work and may need changes by upstream.
Disliking systemd intensely, but not satisfied with alternatives so focusing on taming systemd.
clean chroot building not flexible enough ?
Try clean chroot manager by graysky
Offline
That suggests the sw needs a specific python setup and relies on libraries provided by them instead of system libraries .
I guess this is proprietary software ?
the url= link indicates it's open source.
Yes, it uses a python virtual environment that's being installed by the psono-script.install script used by pacman when installing or upgrading the package.
Edit: removed pacman libc.so patching and added patchelf to build process to replace libc.so with libc.so.6 in pyarmor_runtime.so ELF in the Psono software to solve the glibc package tampering. Tested in live environment and confirmed working.
psono-script.install looks like it's intended to be run as user with elevated rights for certain parts .
Such scripts are not suitable for packages and are only useful to see what things need to be done.
pip is only useful for user environments and is blocked from systemwide stuff, updating systemwide packages is the job of pacman.
Some of it yes:
- pre_install() create a new system user and system group called psono with it's home folder located at /var/lib/psono where the python application and the virtual environments for it are stored. This user has it's login disabled
- post_install() uses sudo (I think I'll switch this to the runuser command and get rid of the sudo dependancy) to execute commands as the psono user, the commands create a python virtual environment, upgrades pip in that python virtual environment (not the system package) and installs packages designated in psono's requirements.txt file. It does not install, update, modify system packages in any way, shape or form. The python virtual environment is in the psono user's home folder.
To package this software for archlinux you'd probably have to disable the auto-update feature and create packages for psono-server-ee and psono-fileserver .
Split them up you mean? That can be done with ease. I'll have to remove the userdel from pre_remove() then. If both packages are installed they'll both use the same user and a manual cleanup may be required. I could also have a package each for the web client and the web admin created. Also what auto update feature? The migrate command you mean?
The pre_remove() function makes changes to /root/ user settings and archlinux packages are forbidden to touch user stuff .
Understood, I'll pick a more appropriate location for a configuration backup and a backup of the encrypted files from the fileserver. The configuration files have secrets for the database so I believe it's appropriate to create a backup of them just in case. Without those same secrets the postgresql database and the encrypted files are useless and can't be reused if that is the intention.
Edit: moved the location to /opt/backups/psono-backup
The services and timer files should not be included in the packages, but put somewhere in a vcs (git) repository so they can be maintained and updated when needed.
Can be done no problem. I just used this on my personal GitLab server so I could update my personal repository with it. I can upload it to GitHub and link it here if you wish to take a look at it.
It might be possible to use a custom DL-agent for the docker part.
It's already part of the PKGBUILD file. You might have missed it. Search for the docker_fetch() function. Every time the package is built a command in prepare() calls the docker_fetch() function and grabs the latest release of the server and fileserver from docker's hub.
The reason I'm creating a new user is so the systemd services run the software with the psono user's user permision. No elevated access, so it can only run what it needs to. I'm basically doing what for example postgresql does when it creates the postgres user and runs the service as that user. Here is the Psono server service file for example:
# /usr/lib/systemd/system/psono-server-ee.service
[Unit]
Description=Psono Password Manager - Enterprise Edition Service
After=network.target network-online.target
Wants=network-online.target
[Service]
Type=notify
TimeoutSec=120
# Psono user specific settings
User=psono
Group=psono
LogsDirectory=psono
StateDirectory=psono
SyslogIdentifier=psono
WorkingDirectory=/var/lib/psono/psono-server-ee/psono
Environment=HOME=/var/lib/psono
# Executable settings
ExecStart=/var/lib/psono/.python_env/psono-server-ee-3.14/bin/gunicorn --bind 0.0.0.0:10100 wsgi
KillMode=mixed
KillSignal=SIGINT
RestartForceExitStatus=100
TimeoutSec=15min
# Additional security-related features
PrivateTmp=true
ProtectHome=true
ProtectSystem=full
NoNewPrivileges=true
ProtectControlGroups=true
ProtectKernelModules=true
ProtectKernelTunables=true
PrivateDevices=true
RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6
RestrictNamespaces=true
RestrictRealtime=true
SystemCallArchitectures=native
[Install]
WantedBy=multi-user.targetLet me know what you think.
Last edited by 7thCore (Yesterday 10:38:05)
The Linux philosophy is 'Laugh in the face of danger'. Oops. Wrong One. 'Do it yourself'. Yes, that's it.
Offline
things have improved.
prepare() - docker fetch
makepkg has a special feature DLAGENTS .
Using this you would add the docker image in source= array and use a custom DLAGENT to download the image.
No idea if that's possible for docker_fetch, but it's worth it to look into.
Note that you should choose which tools are needed to build (and add them to makedeps unless they're a member of base-devel) .
Don't check for curl/wget , choose one and use that.
makedepends are only needed during build and can/should be removed after.
# Given a JSON input on stdin, extract the string value associated with the
# specified key. This avoids an extra dependency on a tool like `jq`.
extract() {
local key="$1"
# Extract "<key>":"<val>" (assumes key/val won't contain double quotes).
# The colon may have whitespace on either side.
grep -o "\"${key}\"[[:space:]]*:[[:space:]]*\"[^\"]\+\"" |
# Extract just <val> by deleting the last '"', and then greedily deleting
# everything up to '"'.
sed -e 's/"$//' -e 's/.*"//'
}jq is already a makedepend, why not use it ?
from install script
printf "\e[32mUpdating Python packages from requirements.txt for Psono Fileserver\e[0m\n"
runuser -l psono -s /bin/bash -c "/usr/bin/python3.14 -m venv /var/lib/psono/.python_env/psono-fileserver-3.14"
runuser -l psono -s /bin/bash -c "/var/lib/psono/.python_env/psono-fileserver-3.14/bin/python3.14 -m pip install --upgrade pip"
runuser -l psono -s /bin/bash -c "/var/lib/psono/.python_env/psono-fileserver-3.14/bin/pip3.14 install -r /var/lib/psono/psono-fileserver/requirements.txt"
runuser -l psono -s /bin/bash -c "/var/lib/psono/.python_env/psono-fileserver-3.14/bin/pip3.14 install gunicorn"commands like those are ok for a user virtual python environment but I've never seen them used for a systemwide python app install .
It's questionable if AUR moderators will accept this approach, but it will definitely block adoption of this package into official repos .
Package those applications following https://wiki.archlinux.org/title/Python … guidelines is much better (though likely harder)
Disliking systemd intensely, but not satisfied with alternatives so focusing on taming systemd.
clean chroot building not flexible enough ?
Try clean chroot manager by graysky
Offline
I think a much better approach would be to move the most egregious steps, especially the 'pip' installs inside the venv, from the install script to a build() function in the PKGBUILD. Since it's running in a venv, they can (should) be performed by an unprivileged user at build time. And then use the install() function to move the resultant files into /var/lib/psono, owed by the 'psono' user.
However, if this package already uses both venv and docker images, it does raise the question: why isn't this running entirely in a container? Or vice-versa: entirely without needing the Docker overhead and networking/file management pains?
Offline
So you're suggesting I do something like this in PKGBUILD?
build() {
printf "\e[32mPreparing Psono Server Enterprise Edition python virtual environment\e[0m\n"
/usr/bin/python3.14 -m venv ${srcdir}/python_env/psono-server-ee-3.14
PIP_CONFIG_FILE="${srcdir}/conf_psono-python-pip.conf" ${srcdir}/python_env/psono-server-ee-3.14/bin/python3.14 -m pip install --upgrade pip
PIP_CONFIG_FILE="${srcdir}/conf_psono-python-pip.conf" ${srcdir}/python_env/psono-server-ee-3.14/bin/pip3.14 install -r ${srcdir}/psono-ee-src/requirements.txt
if [ "$(uname -m)" = "x86_64" ]; then
PIP_CONFIG_FILE="${srcdir}/conf_psono-python-pip.conf" ${srcdir}/python_env/psono-server-ee-3.14/bin/pip3.14 install -r ${srcdir}/psono-ee-src/requirements-amd64.txt
fi
PIP_CONFIG_FILE="${srcdir}/conf_psono-python-pip.conf" ${srcdir}/python_env/psono-server-ee-3.14/bin/pip3.14 install gunicorn
printf "\e[32mChanging paths of python virtual environment files\e[0m\n"
find ${srcdir}/python_env/psono-server-ee-3.14 -type f ! -type l -exec sed -i "s|${srcdir}/python_env/psono-server-ee-3.14|/var/lib/psono/.python_env/psono-server-ee-3.14|g" {} +
printf "\e[32mDeleting python virtual environment cache files\e[0m\n"
find ${srcdir}/python_env/psono-server-ee-3.14/lib/python3.14/site-packages -type f -name "*.pyc" -delete -o -type d -name "__pycache__" -exec rm -rf {} +
printf "\e[32mPreparing Psono File Server python virtual environment\e[0m\n"
/usr/bin/python3.14 -m venv ${srcdir}/python_env/psono-fileserver-3.14
PIP_CONFIG_FILE="${srcdir}/conf_psono-python-pip.conf" ${srcdir}/python_env/psono-fileserver-3.14/bin/python3.14 -m pip install --upgrade pip
PIP_CONFIG_FILE="${srcdir}/conf_psono-python-pip.conf" ${srcdir}/python_env/psono-fileserver-3.14/bin/pip3.14 install -r ${srcdir}/psono-fs-src/requirements.txt
PIP_CONFIG_FILE="${srcdir}/conf_psono-python-pip.conf" ${srcdir}/python_env/psono-fileserver-3.14/bin/pip3.14 install gunicorn
printf "\e[32mChanging paths of python virtual environment files\e[0m\n"
find ${srcdir}/python_env/psono-fileserver-3.14 -type f ! -type l -exec sed -i "s|${srcdir}/python_env/psono-fileserver-3.14|/var/lib/psono/.python_env/psono-fileserver-3.14|g" {} +
printf "\e[32mDeleting python virtual environment cache files\e[0m\n"
find ${srcdir}/python_env/psono-fileserver-3.14/lib/python3.14/site-packages -type f -name "*.pyc" -delete -o -type d -name "__pycache__" -exec rm -rf {} +
}And remove it from the psono-ee.install like so:
pre_install() {
getent group psono >/dev/null || groupadd --system psono
getent passwd psono >/dev/null || useradd --system -g psono -d /var/lib/psono -s /usr/bin/nologin psono
}
post_install() {
printf "\e[1;31mDisclaimer: This AUR package is maintained by the community and is not\e[0m\n"
printf "\e[1;31mofficially supported by the software developers or the package maintainer.\e[0m\n"
printf "\e[1;31mUse this package at your own risk. The developers of the original software\e[0m\n"
printf "\e[1;31mand the package maintainer are not responsible for any issues, bugs, or\e[0m\n"
printf "\e[1;31mdamages resulting from its use. For installation or usage questions, please\e[0m\n"
printf "\e[1;31mdo not contact the original developers. Instead, seek assistance from the\e[0m\n"
printf "\e[1;31mpackage maintainer, the Arch Linux community or relevant forums.\e[0m\n"
printf "\e[32mDon't forget to setup your Psono configuration and execute the following command to complete the Psono installation before starting the services:\e[0m\n"
printf "\e[32m'runuser -l psono -s /bin/bash -c \"/var/lib/psono/.python_env/psono-server-ee-3.14/bin/python3.14 /var/lib/psono/psono-server-ee/psono/manage.py migrate\"'\e[0m\n"
chown -R psono:psono /var/lib/psono
chown -R psono:psono /var/log/psono
}
post_upgrade() {
printf "\e[1;31mDisclaimer: This AUR package is maintained by the community and is not\e[0m\n"
printf "\e[1;31mofficially supported by the software developers or the package maintainer.\e[0m\n"
printf "\e[1;31mUse this package at your own risk. The developers of the original software\e[0m\n"
printf "\e[1;31mand the package maintainer are not responsible for any issues, bugs, or\e[0m\n"
printf "\e[1;31mdamages resulting from its use. For installation or usage questions, please\e[0m\n"
printf "\e[1;31mdo not contact the original developers. Instead, seek assistance from the\e[0m\n"
printf "\e[1;31mpackage maintainer, the Arch Linux community or relevant forums.\e[0m\n"
chown -R psono:psono /var/lib/psono
chown -R psono:psono /var/log/psono
}
pre_remove() {
printf "\e[32mBacking up Psono configuration and shards to /opt/backups/psono-backup\e[0m\n"
mkdir -p /opt/backups/psono-backup
cp /etc/nginx/sites-available/psono-ee-combo.conf /opt/backups/psono-backup/psono-ee-combo-nginx.conf
cp /var/lib/psono/.psono_server/settings.yaml /opt/backups/psono-backup/server_settings.yaml
cp /var/lib/psono/.psono_fileserver/settings.yaml /opt/backups/psono-backup/fileserver_settings.yaml
cp -rf /var/lib/psono/psono-shard /opt/backups/psono-backup/
}
post_remove() {
userdel --remove psono
rm /etc/nginx/sites-available/psono-ee-combo.conf
rm /etc/nginx/sites-enabled/psono-ee-combo.conf
rm -rf /usr/share/webapps/psono-webclient
}Well I tried it in a live environment and it works. The package is however 130MB in size tho,but it works.
The reason the Psono developers are using both docker and venv is, I belive, because they can control the environment easily and administrators can update the software via docker. Creates less problems. Psono has quite an extensive list of requirements to function, some are even not available in the Arch Linux repository.
Edit: the find commands had to be added so the python cache is regenerated on first execution on a machine that the package was installed to and the other find command changes paths, otherwise it will still have the ${srcdir} paths and the venv won't function at all.
Edit 2: Let me know if this solution is acceptable and if so, I'll edit the original post to include it.
Edit 3: Removed checks for curl and wget from docker_fetch(), recoded docker_fetch() to only use curl and jq, removed wget as make dependancy
Last edited by 7thCore (Yesterday 22:39:10)
The Linux philosophy is 'Laugh in the face of danger'. Oops. Wrong One. 'Do it yourself'. Yes, that's it.
Offline
I'd say it's MUCH better now that you "build" the package in the build() function and not have any binaries created/installed during the install function. As for the 130MB in size: if that is true representation of the size that gets installed, then that's actually another big benefit: pacman will now accurately check available disk space before installing.
As a sanity check: compare the full size of the files installed with the "old" method of doing the full build during the install() to what pacman believes the install requires for the 130MB package. If those are roughly the same, then that's great. If there's a big difference, perhaps you can strip out some files.
find ${srcdir}/python_env/psono-fileserver-3.14/lib/python3.14/site-packages -type f -name "*.pyc" -delete -o -type d -name "__pycache__" -exec rm -rf {} +
I am not an expert in packaging Python packages, so I could be wrong here, but I don't think you want to remove the optimized bytecode files. I know this will inflate the package size even more, but that way pacman keeps track of them. See Python package guidelines. Ctrl-f for "pyc".
Edit: forgot to add this: to create the "psono" user/group, I believe you should be using the systemd.sysusers functionality. This is how the postgresql package creates its 'postgres' user:
=== PKGBUILD:
package() {
...
install -Dm644 postgresql.sysusers "${pkgdir}/usr/lib/sysusers.d/postgresql.conf"
}
=== postgresql.sysusers:
u postgres - "PostgreSQL user" /var/lib/postgres /usr/bin/bashLastly, this might be too subjective, but I personally think you shouldn't pretty-print your "printf's" and just keep it straight plain-text. It will get saved in pacman.log and it makes it harder to automate and search.
Last edited by twelveeighty (Today 00:45:58)
Offline
With building the python environments the installation size gets reduced by 640M because there is no pip cache present in the psono user's .cache directory. The complete file size of extracted files is 450M.
The python_venv directory with the bytecode files is 1.2G and without it's 380M.
I am not an expert in packaging Python packages, so I could be wrong here, but I don't think you want to remove the optimized bytecode files. I know this will inflate the package size even more, but that way pacman keeps track of them. See Python package guidelines. Ctrl-f for "pyc".
From my testing, not cleaning up the bytecode files results in bytecode errors and 100% guaranteed crashing executing any command from both virtual environments on the new installation. I tested with and without the cleanup by building the package and installing it on the same machine. It's most likely a path issue because the python venv gets generated for example in /home/users/psono-ee-combo/src/python_venv/psono-server-ee-3.14 and that path gets passed to the venv and it's bytecode files. Cleaning them up is a necessity to prevent errors from showing up on fresh installations.
forgot to add this: to create the "psono" user/group, I believe you should be using the systemd.sysusers functionality. This is how the postgresql package creates its 'postgres' user:
Added. What about the postgresql.tmpfiles file? It creates the /var/lib postgres/data folder, but that's for an empty folder and postgresql doesn't ship anything in those folders.
Lastly, this might be too subjective, but I personally think you shouldn't pretty-print your "printf's" and just keep it straight plain-text. It will get saved in pacman.log and it makes it harder to automate and search.
Done. First post updated.
Edit: I'll research Lone_Wolf's suggested approach too. I don't quite understand it just yet but I'll see what comes of it.
Last edited by 7thCore (Today 06:53:31)
The Linux philosophy is 'Laugh in the face of danger'. Oops. Wrong One. 'Do it yourself'. Yes, that's it.
Offline