diff --git a/salt/sys-cacher/README.md b/salt/sys-cacher/README.md index 810bbb58..553b9041 100644 --- a/salt/sys-cacher/README.md +++ b/salt/sys-cacher/README.md @@ -106,13 +106,30 @@ non-template qubes and qubes that do not have a working Qrexec. Use the native configuration to set the update proxy using the IP address of `sys-cacher` by setting `sys-cacher` as the netvm of the client qube. +Set `sys-cacher` as the netvm of your qube: +```sh +qvm-prefs QUBE netvm sys-cacher +``` + +Enable the service `netvm-cacher`: +```sh +qvm-features QUBE service.netvm-cacher 1 +``` + +Copy [apt-cacher-ng-repo](files/client/bin/apt-cacher-ng-repo) to your qube +and set the script to run on boot. Make sure that the file +`/var/run/qubes-service/netvm-cacher` exists on every startup for the proxy +address change take effect. + +The qube has to be restarted for changes to take effect. + ### Non-TemplateVMs integration **Attention**: this method will allow a client qube to bypass the qubes -firewall and connect to a remote via the updates proxy. +firewall and connect to a remote host via the updates proxy. By default, only templates will use the proxy to update, if you want to cache -Non-TemplateVMs updates or simply make them functional again, the qube will +non-TemplateVMs updates or simply make them functional again, the qube will need the `service.updates-proxy-setup` feature set: ```sh qvm-tags add QUBE updatevm-sys-cacher diff --git a/salt/sys-cacher/files/client/bin/apt-cacher-ng-repo b/salt/sys-cacher/files/client/bin/apt-cacher-ng-repo index 0135cce1..425717cd 100755 --- a/salt/sys-cacher/files/client/bin/apt-cacher-ng-repo +++ b/salt/sys-cacher/files/client/bin/apt-cacher-ng-repo @@ -1,106 +1,303 @@ #!/bin/sh # SPDX-FileCopyrightText: 2024 Benjamin Grande M. S. +# SPDX-FileCopyrightText: 2015 - 2020 Marek Marczykowski-Gorecki # -# SPDX-License-Identifier: AGPL-3.0-or-later +# SPDX-License-Identifier: GPL-2.0-only + +## Description: rewrite repositories definitions to be used with the cacher. +## It works for qubes that should be configured to use the cacher via Qrexec +## or Netvm (direct networking). +## +## Looping through files and testing their permissions (read, write) is better +## than finding a file and trying to sed it without knowledge, it is also +## beneficial as 'find' fails if file is not existent and sending all 'find' +## output to /dev/stderr is not great. +## +## Assigning the repositories files to '$@' avoids having to parse their names +## in case they contain spaces, newlines and other dangerous characters to the +## shell, it is also an easy way to use an array for /bin/sh. set -eu -changes_file="$(mktemp)" -trap 'rm -f "${changes_file}"' HUP INT QUIT ABRT EXIT +set_proxy_marker(){ + marker_begin_text="QUBES BEGIN" + marker_end_text="QUBES END" + marker_begin="### ${marker_begin_text} ###" + marker_end="### ${marker_end_text} ###" + proxy_file="${1}" + proxy_options="${2}" + + if ! grep -q "^${marker_begin}$" "${proxy_file}"; then + if grep -q "^${marker_end}$" "${proxy_file}"; then + echo "Error: found marker ${marker_end_text} but not ${marker_begin_text} in ${proxy_file}" >&2 + echo "Fix the file by either removing both markers or adding missing ones and retry" >&2 + exit 1 + fi + cp "${proxy_file}" "${proxy_file}.qubes-orig" + echo "${marker_begin}" | tee -a "${proxy_file}" >/dev/null + echo "${marker_end}" | tee -a "${proxy_file}" >/dev/null + elif ! grep -q "^${marker_end}$" "${proxy_file}"; then + echo "Error: found marker ${marker_begin_text} but not ${marker_end_text} in ${proxy_file}" >&2 + echo "Fix the file by either removing both markers or adding missing ones and retry" >&2 + exit 1 + fi -rewrite_repo(){ - test -n "${2}" || return 1 - test -f "${repo}" || return 0 - test -r "${repo}" || return 0 - test -w "${repo}" || return 0 - sed -i "s|${1}|${2}|w ${changes_file}" "${repo}" + proxy_tmp_file="$(mktemp)" + cat >"${proxy_tmp_file}" </dev/null + fi + ## GNU Sed, only reliable while we don't support BSD. + sed -i -e "/^${marker_begin}$/,/^${marker_end}$/{ + /^${marker_end}$/b + /^${marker_begin}$/!d + r ${proxy_tmp_file} + }" "${proxy_file}" + rm -f "${proxy_tmp_file}" } -usage(){ - echo "Usage: ${0##*/} [install|uninstall]" - exit 1 +check_netvm_cacher(){ + proxy_host="127.0.0.1" + proxy_port="8082" + proxy_addr="" + proxy_url="" + proxy_conf="" + if ! test -f /var/run/qubes-service/updates-proxy-setup; then + return 0 + fi + if test -f /var/run/qubes-service/netvm-cacher; then + proxy_host="$(qubesdb-read /qubes-gateway)" + if test -z "${proxy_host}"; then + echo "Error: service netvm-cacher enabled but netvm IP was not found" >&2 + return 1 + fi + fi + proxy_addr="${proxy_host}:${proxy_port}" + proxy_url="http://${proxy_addr}" + proxy_conf="proxy=${proxy_addr}" } -case "${1-}" in - install|uninstall) action="${1}";; - *) usage;; -esac -action="${1}" +set_proxy_os(){ + if test -e /etc/fedora-release; then + ## Fedora + + if test -w /etc/dnf/dnf.conf; then + set_proxy_marker /etc/dnf/dnf.conf "${proxy_conf}" + fi + + if test -n "${proxy_addr}"; then + cat >/etc/yum.conf.d/qubes-proxy.conf </dev/null || true ;; esac - done - -elif test -e /etc/debian_version && test ! -e /usr/share/whonix/marker; then - ## Debian but not Whonix. - for repo in \ - /etc/apt/sources.list \ - /etc/apt/sources.list.d/*.list \ - /etc/apt/sources.list.d/*.sources - do + + elif test -e /etc/debian_version && test ! -e /usr/share/whonix/marker; then + ## Debian but not Whonix. + + if test -n "${proxy_addr}"; then + cat >/etc/apt/apt.conf.d/50cacher-proxy </run/qubes/bin/pacman </etc/profile.d/qubes-proxy.sh << EOF +export PATH=/run/qubes/bin:\$PATH +EOF + else + rm -f /run/qubes/bin/pacman /etc/profile.d/qubes-proxy.sh + fi + + set -- + for repo in \ + /etc/pacman.d/mirrorlist \ + /etc/pacman.d/*.conf \ + /etc/pacman.d/*.conf.disabled + do + test -f "${repo}" || continue + test -r "${repo}" || continue + test -w "${repo}" || continue + set -- "${@}" "${repo}" + done + test -n "${*}" || return 0 + case "${action}" in install) - rewrite_repo "Server\s*=\s*https://" "Server = http://HTTPS///" + find "${@}" -type f -exec sed -i \ + -e "s|Server\s*=\s*https://|Server = http://HTTPS///|w ${changes_file}" \ + {} \+ ;; + uninstall) - rewrite_repo "Server\s*=\s*http://HTTPS///" "Server = https://" + find "${@}" -type f -exec sed -i \ + -e "s|Server\s*=\s*http://HTTPS///|Server = https://|w ${changes_file}" \ + {} \+ ;; esac - done + else + ## TODO: Gentoo. + echo "Cacher does not support your Operating System distribution." >&2 + exit 1 + fi +} + +set_proxy_unspecific_os(){ + if test -w /etc/PackageKit/PackageKit.conf; then + set_proxy_marker /etc/PackageKit/PackageKit.conf "ProxyHTTP=${proxy_url}" + fi +} + +usage(){ + echo "Usage: ${0##*/} [install|uninstall]" + echo "Note: autodetection occurs if not argument is specified" + exit 1 +} + +changes_file="$(mktemp)" +trap 'rm -f "${changes_file}"' HUP INT QUIT ABRT EXIT + +if test -f /var/run/qubes-service/updates-proxy-setup || + test -f /var/run/qubes-service/netvm-cacher +then + action="install" else - echo "Cacher does not support your Operating System distribution." >&2 + action="uninstall" +fi + +case "${1-}" in + install|uninstall) action="${1}";; + "") ;; + *) usage;; +esac + +if test "$(id -u)" != "0"; then + echo "Error: Permission denied, action requires root privileges." exit 1 fi -## Stateful cmd module. +check_netvm_cacher +set_proxy_os +set_proxy_unspecific_os + +## Stateful Salt cmd Module. echo if test -s "${changes_file}"; then - echo "changed=yes comment='URIs have been modified'" + echo "changed=yes comment='configuration was modified'" else - echo "changed=no comment='URIs remained untouched'" + echo "changed=no comment='configuration remained untouched'" fi exit diff --git a/salt/sys-cacher/files/client/systemd/qubes-apt-cacher-ng-repo.service b/salt/sys-cacher/files/client/systemd/qubes-apt-cacher-ng-repo.service new file mode 100644 index 00000000..01d51341 --- /dev/null +++ b/salt/sys-cacher/files/client/systemd/qubes-apt-cacher-ng-repo.service @@ -0,0 +1,15 @@ +# SPDX-FileCopyrightText: 2024 Benjamin Grande M. S. +# +# SPDX-License-Identifier: AGPL-3.0-or-later + +[Unit] +Description=Dynamically write repository definitions to be used by apt-cacher-ng +After=qubes-mount-dirs.service +Before=qubes-update-check.service + +[Service] +Type=oneshot +ExecStart=/usr/bin/qubes/apt-cacher-ng-repo + +[Install] +WantedBy=multi-user.target diff --git a/salt/sys-cacher/install-client.sls b/salt/sys-cacher/install-client.sls index 34519612..2b5cc642 100644 --- a/salt/sys-cacher/install-client.sls +++ b/salt/sys-cacher/install-client.sls @@ -4,17 +4,33 @@ SPDX-FileCopyrightText: 2023 - 2024 Benjamin Grande M. S.