You are not logged in.

#1 2026-03-12 10:24:49

7thCore
Member
Registered: 2018-06-09
Posts: 66

PKGBUILD Review: psono-ee-combo

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')
license=('Apache-2.0')
depends=('bash'
        'coreutils'
        'gcc'
        'git'
        'glibc'
        'haveged'
        'libb2'
        'libffi'
        'libldap'
        'libpqxx'
        'libsasl'
        'libyaml'
        'nginx'
        'openssl'
        'postgresql'
        'python=3.14'
        'sudo'
        'util-linux')
optdepends=('logrotate: rotates system logs automatically')
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/logrotate.d/psono'
        'etc/nginx/sites-available/psono-nginx.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_fileserver_settings.yaml'
        'conf_pip.conf'
        'conf_psono.logrotate'
        'conf_psono-nginx.conf'
        'conf_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=('7d658724229b49a4e69e45e0a57b536a42ec02ad1c3343539b21f8fa505c1002'
            '45d4604c640b220af6625dbfa6b9fa939ebb00ae2d24bf0e9e1ce8643087a5cc'
            'bd391b1824d182c3d5813ca71535d5e47c2404883f1bc58f76b677fde3d6e70f'
            'd37056ba5d8a24a03337d7816cbc47c115c0b01036b8e9c5d1cef02388b677b3'
            '6316939b8c5a36b1b3c379a50d5a86a2d4c153a4e38ec7b2b2e18da7ad7db34d'
            'b3cdc9d315b628f0970459a4af08bbe4b5c08e1b8a0dff8da7f5a0c6875c76f9'
            '5f461e6094fd241057c1cea99b1b432a0a197316efa2f7ab4a87969ec20c24d3'
            'd9f9810503879afd9774e399d1efe6d1f3dfe3aaa017f0ce16010ff8549a858d'
            '4a171e8c0ee529bad90ad37e6633f8dc7cfe40e02fb4cf24f6e95f8084b4584a'
            'd9db1d3c2ee11133dbf2c21f0b7763d172795f289f812e4ac5058c46bf3317f8'
            '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() {
  install -dm755 "${pkgdir}/etc/nginx/sites-available"
  install -dm755 "${pkgdir}/etc/nginx/sites-enabled"
  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_fileserver_settings.yaml" "${pkgdir}/var/lib/psono/.psono_fileserver/settings.yaml"
  install -Dm644 "${srcdir}/conf_pip.conf" "${pkgdir}/var/lib/psono/.pip/pip.conf"
  install -Dm644 "${srcdir}/conf_psono.logrotate" "${pkgdir}/etc/logrotate.d/psono"
  install -Dm644 "${srcdir}/conf_psono-nginx.conf" "${pkgdir}/etc/nginx/sites-available/psono-nginx.conf"
  install -Dm644 "${srcdir}/conf_server_settings.yaml" "${pkgdir}/var/lib/psono/.psono_server/settings.yaml"
  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"
  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
.SRCINFO
PKGBUILD
REUSE.toml
conf_fileserver_settings.yaml
conf_pip.conf
conf_psono-nginx.conf
conf_psono.logrotate
conf_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

REUSE.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-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_fileserver_settings.yaml",
    "conf_pip.conf",
    "conf_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

  echo "Installing Python packages from requirements.txt for Psono Server"
  sudo -u psono /usr/bin/python3.14 -m venv /var/lib/psono/.python_env/psono-server-ee-3.14
  sudo -u psono /var/lib/psono/.python_env/psono-server-ee-3.14/bin/python3.14 -m pip install --upgrade pip
  sudo -u psono /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
    sudo -u psono /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

  sudo -u psono /var/lib/psono/.python_env/psono-server-ee-3.14/bin/pip3.14 install gunicorn

  echo "Installing Python packages from requirements.txt for Psono Fileserver"
  sudo -u psono /usr/bin/python3.14 -m venv /var/lib/psono/.python_env/psono-fileserver-3.14
  sudo -u psono /var/lib/psono/.python_env/psono-fileserver-3.14/bin/python3.14 -m pip install --upgrade pip
  sudo -u psono /var/lib/psono/.python_env/psono-fileserver-3.14/bin/pip3.14 install -r /var/lib/psono/psono-fileserver/requirements.txt
  sudo -u psono /var/lib/psono/.python_env/psono-fileserver-3.14/bin/pip3.14 install gunicorn

  echo "Dont forget to setup your Psono configuration and execute the following command to complete the Psono installation before starting the services:"
  echo "'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'"
}

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/

  echo "Updating Python packages from requirements.txt for Psono Server"
  sudo -u psono /usr/bin/python3.14 -m venv /var/lib/psono/.python_env/psono-server-ee-3.14
  sudo -u psono /var/lib/psono/.python_env/psono-server-ee-3.14/bin/python3.14 -m pip install --upgrade pip
  sudo -u psono /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
    sudo -u psono /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

  sudo -u psono /var/lib/psono/.python_env/psono-server-ee-3.14/bin/pip3.14 install gunicorn

  echo "Updating Python packages from requirements.txt for Psono Fileserver"
  sudo -u psono /usr/bin/python3.14 -m venv /var/lib/psono/.python_env/psono-fileserver-3.14
  sudo -u psono /var/lib/psono/.python_env/psono-fileserver-3.14/bin/python3.14 -m pip install --upgrade pip
  sudo -u psono /var/lib/psono/.python_env/psono-fileserver-3.14/bin/pip3.14 install -r /var/lib/psono/psono-fileserver/requirements.txt
  sudo -u psono /var/lib/psono/.python_env/psono-fileserver-3.14/bin/pip3.14 install gunicorn
}

pre_remove() {
  echo "Backing up Psono configuration and shards to /root/psono-backup"
  mkdir /root/psono-backup
  cp /var/lib/psono/.psono_server/settings.yaml /root/psono-backup/server_settings.yaml
  cp /var/lib/psono/.psono_fileserver/settings.yaml /root/psono-backup/fileserver_settings.yaml
  cp -rf /var/lib/psono/psono-shard /root/psono-backup/
}

post_remove() {
  userdel --remove psono
  rm /etc/nginx/sites-available/psono-nginx.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
  ;;
esac

pacman_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-patch

Questions:
- 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

Last edited by 7thCore (2026-03-12 10:37:18)


[ Arch x86_64 | linux | Asus Prime X570-Pro | AMD Ryzen 9 5900X @4,8Ghz | AMD RX580 | 32GB RAM DDR4 | Main, 2 Monitors ]
[ Arch x86_64 | linux | Asus Pro WS X570-Ace | AMD Ryzen 9 5950X @4,9Ghz | Intel A750 | 128GB RAM DDR4 | Server ]

The Linux philosophy is 'Laugh in the face of danger'. Oops. Wrong One. 'Do it yourself'. Yes, that's it.

Offline

Board footer

Powered by FluxBB