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 <email-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'
'jq'
'sed'
'tar'
'wget')
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/jail.d/psono-ee.conf'
'etc/fail2ban/filter.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-python-pip.conf'
'conf_psono-server-settings.yaml'
'pacman_05-psono-ee-pre.hook'
'pacman_98-psono-ee-glibc.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.service')
sha256sums=('bd391b1824d182c3d5813ca71535d5e47c2404883f1bc58f76b677fde3d6e70f'
'66ac600efad0aa1af7ddfeca5452f369ac3fe8f0e8c9ad90ae1bf73be18460bc'
'5d422995f77d17c65d7827e0af27afb0ba6500e91e17f66fcb758aa322d8108c'
'7d658724229b49a4e69e45e0a57b536a42ec02ad1c3343539b21f8fa505c1002'
'd37056ba5d8a24a03337d7816cbc47c115c0b01036b8e9c5d1cef02388b677b3'
'45d4604c640b220af6625dbfa6b9fa939ebb00ae2d24bf0e9e1ce8643087a5cc'
'6316939b8c5a36b1b3c379a50d5a86a2d4c153a4e38ec7b2b2e18da7ad7db34d'
'b3cdc9d315b628f0970459a4af08bbe4b5c08e1b8a0dff8da7f5a0c6875c76f9'
'5f461e6094fd241057c1cea99b1b432a0a197316efa2f7ab4a87969ec20c24d3'
'd9f9810503879afd9774e399d1efe6d1f3dfe3aaa017f0ce16010ff8549a858d'
'4a171e8c0ee529bad90ad37e6633f8dc7cfe40e02fb4cf24f6e95f8084b4584a'
'162d7319880aa3c68c701fd9553b0963f4d3641b0f05424cd43925030b1e9611'
'ab1c4b8611aff2963c622f4995ab3df8a7fe2958435d5e220b9075a6204134a0'
'af7985b5a1ebf8664888959f8dd9f4d24ada00702548e4e07253eacddacc8403'
'ac7d656c02632ca81fb3683a65764b076e25a5ae39bdd2a4ef9d5827b984e1fe'
'4009d186b42e1c79bebf340899a649a15f2019945dca1d81bcd8ec9455852e97'
'e013719b0a8fd62e4c1d0fc3e83fc1903fc7189205bb58899b7e5fd4a7ae6b26'
'e61be50b496a39b12e40f66bb665eaaff9d3edd3c09db6f39c6116527e3049f7'
'dcd96456d173063200f2ef0a62364b89fb799228870f566c6c84da9d368f5e5b'
'ebc9d9ad66ff7cfdbf4698b2ce24392b1a52ff6a0294f72288e14be1ede6219b'
'9f7ff36e2dc7db569d46a84b1232737b5a3ed77190fb01f524a478941b5d36c5')
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"
have_curl() {
command -v curl >/dev/null
}
have_wget() {
command -v wget >/dev/null
}
image_spec="$1"
image="${image_spec%%:*}"
if [ "${image#*/}" = "${image}" ]; then
# Docker official images are in the 'library' namespace.
image="library/${image}"
fi
ref="${image_spec#*:}"
# Split platform (OS/arch/variant) into separate variables.
# A platform specifier doesn't always include the `variant` component.
OLD_IFS="${IFS}"
IFS=/ read -r OS ARCH VARIANT <<-EOF
${PLATFORM}
EOF
IFS="${OLD_IFS}"
# 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/.*"//'
}
# Fetch a URL to stdout. Up to two header arguments may be specified:
#
# fetch <url> [name1: value1] [name2: value2]
#
fetch() {
if have_curl; then
if [ $# -eq 2 ]; then
set -- -H "$2" "$1"
elif [ $# -eq 3 ]; then
set -- -H "$2" -H "$3" "$1"
fi
curl -sSL "$@"
else
if [ $# -eq 2 ]; then
set -- --header "$2" "$1"
elif [ $# -eq 3 ]; then
set -- --header "$2" --header "$3" "$1"
fi
wget -qO- "$@"
fi
}
# https://docs.docker.com/docker-hub/api/latest/#tag/repositories
manifest_list_url="https://hub.docker.com/v2/repositories/${image}/tags/${ref}"
# If the ref is already a SHA-256 image digest, then we don't need to look up anything.
if [ -z "${ref##sha256:*}" ]; then
digest="${ref}"
else
echo "Getting multi-arch manifest list..."
NL='
'
digest=$(fetch "${manifest_list_url}" |
# Break up the single-line JSON output into separate lines by adding
# newlines before and after the chars '[', ']', '{', and '}'.
# This uses the \${NL} syntax because some BSD variants of sed don't
# support \n syntax in the replacement string, but instead require
# a literal newline preceded by a backslash.
sed -e 's/\([][{}]\)/\'"${NL}"'\1\'"${NL}"'/g' |
# Extract the "images":[...] list.
sed -n '/"images":/,/]/ p' |
# Each image's details are now on a separate line, e.g.
# "architecture":"arm64","features":"","variant":"v8","digest":"sha256:054c85801c4cb41511b176eb0bf13a2c4bbd41611ddd70594ec3315e88813524","os":"linux","os_features":"","os_version":null,"size":828724,"status":"active","last_pulled":"2022-09-02T22:46:48.240632Z","last_pushed":"2022-09-02T00:42:45.69226Z"
# The image details are interspersed with lines of stray punctuation,
# so grep for an arbitrary string that must be in these lines.
grep architecture |
# Search for an image that matches the platform.
while read -r image; do
# Arch is probably most likely to be unique, so check that first.
arch="$(echo ${image} | extract 'architecture')"
if [ "${arch}" != "${ARCH}" ]; then continue; fi
os="$(echo ${image} | extract 'os')"
if [ "${os}" != "${OS}" ]; then continue; fi
variant="$(echo ${image} | extract 'variant')"
if [ "${variant}" = "${VARIANT}" ]; then
echo ${image} | extract 'digest'
break
fi
done)
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
# https://docs.docker.com/registry/spec/auth/token/#how-to-authenticate
api_token_url="https://auth.docker.io/token?service=registry.docker.io&scope=repository:$image:pull"
# https://github.com/docker/distribution/blob/master/docs/spec/api.md#pulling-an-image-manifest
manifest_url="https://registry-1.docker.io/v2/${image}/manifests/${digest}"
# https://github.com/docker/distribution/blob/master/docs/spec/api.md#pulling-a-layer
blobs_base_url="https://registry-1.docker.io/v2/${image}/blobs"
echo "Getting API token..."
token=$(fetch "${api_token_url}" | extract 'token')
auth_header="Authorization: Bearer $token"
# https://github.com/distribution/distribution/blob/main/docs/spec/manifest-v2-2.md
docker_manifest_v2="application/vnd.docker.distribution.manifest.v2+json"
# https://github.com/opencontainers/image-spec/blob/main/manifest.md
oci_manifest_v1="application/vnd.oci.image.manifest.v1+json"
# Docker Hub can return either type of manifest format. Most images seem to
# use the Docker format for now, but the OCI format will likely become more
# common as features that require that format become enabled by default
# (e.g., https://github.com/docker/build-push-action/releases/tag/v3.3.0).
accept_header="Accept: ${docker_manifest_v2},${oci_manifest_v1}"
echo "Getting image manifest for $image:$ref..."
layers=$(fetch "${manifest_url}" "${auth_header}" "${accept_header}" |
# Extract `digest` values only after the `layers` section appears.
sed -n '/"layers":/,$ p' |
extract '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 -
# Ref: https://github.com/moby/moby/blob/master/image/spec/v1.2.md#creating-an-image-filesystem-changeset
# https://github.com/moby/moby/blob/master/pkg/archive/whiteouts.go
# Search for "whiteout" files to indicate files deleted in this layer.
OLD_IFS="${IFS}"
find "${OUT_DIR}" -name '.wh.*' | while IFS= read -r f; do
dir="${f%/*}"
wh_file="${f##*/}"
file="${wh_file#.wh.}"
# Delete both the whiteout file and the whited-out file.
rm -rf "${dir}/${wh_file}" "${dir}/${file}"
done
IFS="${OLD_IFS}"
done
echo "Image contents extracted into ${OUT_DIR}."
}
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"
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"
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"
printf "\e[32mFetching Psono Server Enterprise Edition Docker image\e[0m\n"
docker_fetch psono/psono-combo-enterprise:latest "$PLATFORM_DEFAULT"
printf "\e[32mExtracting Psono Server Enterprise Edition from Docker image\e[0m\n"
mv ${srcdir}/psono-src-docker/root/* ${srcdir}/psono-ee-src/
printf "\e[32mExtracting Psono Admin Portal from Docker image\e[0m\n"
mv ${srcdir}/psono-src-docker/usr/share/nginx/html/portal/* "${srcdir}/psono-web-admin/"
printf "\e[32mExtracting Psono Web Portal from Docker image\e[0m\n"
mv ${srcdir}/psono-src-docker/usr/share/nginx/html/* "${srcdir}/psono-web/"
printf "\e[32mRemoving unused files of Psono Server Enterprise Edition Docker image\e[0m\n"
rm -rf ${srcdir}/psono-src-docker/*
printf "\e[32mFetching Psono File Server Docker image\e[0m\n"
docker_fetch psono/psono-fileserver:latest "$PLATFORM_DEFAULT"
printf "\e[32mExtracting Psono File Server from Docker image\e[0m\n"
mv ${srcdir}/psono-src-docker/root/* ${srcdir}/psono-fs-src/
printf "\e[32mRemoving unused files of Psono File Server Docker image\e[0m\n"
rm -rf ${srcdir}/psono-src-docker/*
printf "\e[32mPatching Psono Server Enterprise Edition requirements.txt\e[0m\n"
cd "${srcdir}/psono-ee-src"
patch -Np1 -i "${srcdir}/psono-ee-server-requirements.patch"
}
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/jail.d/psono-ee.conf"
install -Dm644 "${srcdir}/conf_psono-fail2ban-jail.local" "${pkgdir}/etc/fail2ban/filter.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_98-psono-ee-glibc.hook" "${pkgdir}/usr/share/libalpm/hooks/98-psono-ee-glibc.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-backups"
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/lib/psono/.python_env/psono-fileserver"
install -dm755 "${pkgdir}/var/lib/psono/.python_env/psono-server-ee"
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}/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/"
}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-python-pip.conf
conf_psono-server-settings.yaml
conf_psono.logrotate
pacman_05-psono-ee-pre.hook
pacman_98-psono-ee-glibc.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-python-pip.conf",
"conf_psono-server-settings.yaml",
]
SPDX-FileCopyrightText = "psono-ee-combo contributors"
SPDX-License-Identifier = "Apache-2.0"psono-script.install
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"
chown -R psono:psono /var/lib/psono
printf "\e[32mInstalling Python packages from requirements.txt for Psono Server\e[0m\n"
runuser -l psono -s /bin/bash -c "/usr/bin/python3.14 -m venv /var/lib/psono/.python_env/psono-server-ee-3.14"
runuser -l psono -s /bin/bash -c "/var/lib/psono/.python_env/psono-server-ee-3.14/bin/python3.14 -m pip install --upgrade pip"
runuser -l psono -s /bin/bash -c "/var/lib/psono/.python_env/psono-server-ee-3.14/bin/pip3.14 install -r /var/lib/psono/psono-server-ee/requirements.txt"
if [ "$(uname -m)" = "x86_64" ]; then
runuser -l psono -s /bin/bash -c "/var/lib/psono/.python_env/psono-server-ee-3.14/bin/pip3.14 install -r /var/lib/psono/psono-server-ee/requirements-amd64.txt"
fi
runuser -l psono -s /bin/bash -c "/var/lib/psono/.python_env/psono-server-ee-3.14/bin/pip3.14 install gunicorn"
printf "\e[32mInstalling 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"
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"
}
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/
printf "\e[32mUpdating Python packages from requirements.txt for Psono Server\e[0m\n"
runuser -l psono -s /bin/bash -c "/usr/bin/python3.14 -m venv /var/lib/psono/.python_env/psono-server-ee-3.14"
runuser -l psono -s /bin/bash -c "/var/lib/psono/.python_env/psono-server-ee-3.14/bin/python3.14 -m pip install --upgrade pip"
runuser -l psono -s /bin/bash -c "/var/lib/psono/.python_env/psono-server-ee-3.14/bin/pip3.14 install -r /var/lib/psono/psono-server-ee/requirements.txt"
if [ "$(uname -m)" = "x86_64" ]; then
runuser -l psono -s /bin/bash -c "/var/lib/psono/.python_env/psono-server-ee-3.14/bin/pip3.14 install -r /var/lib/psono/psono-server-ee/requirements-amd64.txt"
fi
runuser -l psono -s /bin/bash -c "/var/lib/psono/.python_env/psono-server-ee-3.14/bin/pip3.14 install gunicorn"
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"
}
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
}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
}
#Backup and symlink libc.so to prevent python ELF errors in Psono
glibc_elf_patch() {
if [ -f /usr/lib/libc.so ] && [ -f /usr/lib/libc.so.6 ]; then
if [ -f /var/lib/psono/libc.so.bak ]; then
rm /var/lib/psono/libc.so.bak
fi
mv /usr/lib/libc.so /var/lib/psono/libc.so.bak
ln -s /usr/lib/libc.so.6 /usr/lib/libc.so
fi
}
#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/psono/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
;;
glibc-elf-patch)
glibc_elf_patch
;;
migrate)
psono_migrate_start
;;
*)
exit 1
;;
esacpacman_98-psono-ee-glibc.hook
[Trigger]
Operation = Install
Operation = Upgrade
Type = Package
Target = glibc
[Action]
Description = Backing up and symlinking libc.so to prevent python ELF errors in Psono - Enterprise Edition
When = PostTransaction
Exec = /usr/share/libalpm/scripts/psono-ee-pacman-hooks.sh glibc-elf-patchQuestions:
- 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?
- 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
Last edited by 7thCore (Yesterday 18:27:37)
The Linux philosophy is 'Laugh in the face of danger'. Oops. Wrong One. 'Do it yourself'. Yes, that's it.
Online
- 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.
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 18:26:40)
The Linux philosophy is 'Laugh in the face of danger'. Oops. Wrong One. 'Do it yourself'. Yes, that's it.
Online