diff --git a/.gitea/workflows/build-publish.yml b/.gitea/workflows/build-publish.yml index 040c6a7..462ea5d 100644 --- a/.gitea/workflows/build-publish.yml +++ b/.gitea/workflows/build-publish.yml @@ -99,13 +99,25 @@ jobs: "${pkg_name}" "${VERSION}" "${ARCH}" "${conflicts}" "${conflicts}" "${pkg_name}" "${TARGET}" \ > "${deb_dir}/control" - # Shared maintainer scripts: - # preinst — backs up /nginx before an upgrade unpacks (so admin - # configs survive the migration off dpkg tracking). - # postinst — restores that backup, then seeds /nginx defaults - # without overwriting any file already there. - cp "${REPO_ROOT}/build/deb/preinst" "${deb_dir}/preinst" - cp "${REPO_ROOT}/build/deb/postinst" "${deb_dir}/postinst" + # Per-package maintainer scripts: + # twiy: + # preinst — backs up /nginx before an upgrade unpacks (so + # admin configs survive the migration off dpkg + # tracking). + # postinst — restores that backup, then seeds any MISSING + # /nginx default after asking the admin (Y/N per + # file); existing configs are never replaced. + # twiy-raweb: + # preinst/postinst — NEVER touch /nginx (no create, update, + # replace, remove, or chown). Only the binary, + # systemd unit, nginx user and log dir are updated. + if [ "${pkg_name}" = "twiy-raweb" ]; then + cp "${REPO_ROOT}/build/deb/preinst-raweb" "${deb_dir}/preinst" + cp "${REPO_ROOT}/build/deb/postinst-raweb" "${deb_dir}/postinst" + else + cp "${REPO_ROOT}/build/deb/preinst" "${deb_dir}/preinst" + cp "${REPO_ROOT}/build/deb/postinst" "${deb_dir}/postinst" + fi chmod 755 "${deb_dir}/preinst" "${deb_dir}/postinst" dpkg-deb --build "${pkg_dir}" diff --git a/build/deb/postinst b/build/deb/postinst index ba44f0d..b02d1e4 100755 --- a/build/deb/postinst +++ b/build/deb/postinst @@ -1,18 +1,39 @@ #!/bin/sh -# postinst — shared by the twiy and twiy-raweb packages. +# postinst — twiy package ONLY (twiy-raweb uses postinst-raweb). # # Config files live under /nginx but are NOT tracked by dpkg. The package # ships an empty /nginx skeleton (so dpkg keeps the dirs across upgrades) plus -# a pristine copy of every config under /usr/share/twiy/defaults/nginx. We -# place configs from that stash here and NEVER overwrite a file that already -# exists — our copy is dropped beside it as .new instead (e.g. -# nginx.conf.new). An upgrade therefore never changes an admin-edited config. +# a pristine copy of every config under /usr/share/twiy/defaults/nginx. +# +# Config policy for twiy: +# - target present (identical OR admin-edited) -> NEVER replace; leave as-is. +# - target absent -> ASK the admin (per file, +# Y/N) and only create it on Y. +# We never drop .new and we never overwrite an existing config, so an +# upgrade can never change an admin-edited config. # # /hostdata is left entirely to the admin: we only make sure the dir exists, # and we never touch or remove its contents. set -e +# Ask the admin a yes/no question on the controlling terminal. Defaults to +# "no" (return 1) whenever we cannot prompt — noninteractive frontend or no +# usable terminal — so a config is never created without explicit consent. +prompt_yes_no() { + msg="$1" + if [ "${DEBIAN_FRONTEND:-}" = noninteractive ] || [ ! -r /dev/tty ]; then + echo "twiy: $msg -> skipped (noninteractive)" + return 1 + fi + printf 'twiy: %s [y/N] ' "$msg" > /dev/tty + read ans < /dev/tty || ans="" + case "$ans" in + [Yy]|[Yy][Ee][Ss]) return 0 ;; + *) return 1 ;; + esac +} + useradd -r -s /bin/false nginx 2>/dev/null || true # Existing dirs are left exactly as they are (mkdir -p is a no-op then). @@ -20,16 +41,17 @@ mkdir -p /nginx /hostdata # Migration: older releases shipped /nginx/* as dpkg-tracked files, so the # upgrade unpack deletes them before this script runs. preinst stashed a copy -# first — restore it now, without clobbering anything already present. +# first — restore the admin's own files now, without clobbering anything +# already present (cp -n). This only puts back what dpkg removed; it never +# introduces new packaged defaults, so no prompt is needed here. if [ -d /var/backups/twiy-nginx ]; then cp -an /var/backups/twiy-nginx/. /nginx/ 2>/dev/null || true rm -rf /var/backups/twiy-nginx fi # Seed packaged defaults: -# - target absent -> install it -# - target present, differs -> keep theirs, drop ours as .new -# - target present, same -> do nothing +# - target present -> do nothing (never replace, no .new). +# - target absent -> ask the admin; create it only if they answer yes. seed_tree() { stash="$1" target="$2" @@ -37,11 +59,15 @@ seed_tree() { find "$stash" -type f | while IFS= read -r src; do rel=${src#$stash/} dst="$target/$rel" - install -d "$(dirname "$dst")" if [ -e "$dst" ]; then - cmp -s "$src" "$dst" || cp -p "$src" "$dst.new" - else + continue + fi + if prompt_yes_no "config '$dst' does not exist. Create it from the packaged default?"; then + install -d "$(dirname "$dst")" cp -p "$src" "$dst" + echo "twiy: created $dst" + else + echo "twiy: skipped $dst" fi done } diff --git a/build/deb/postinst-raweb b/build/deb/postinst-raweb new file mode 100755 index 0000000..a2cfec6 --- /dev/null +++ b/build/deb/postinst-raweb @@ -0,0 +1,26 @@ +#!/bin/sh +# postinst — twiy-raweb package ONLY. +# +# STRICT RULE: this package MUST NOT touch /nginx in any way. It never creates, +# updates, replaces, removes, or re-owns any file or directory under /nginx. +# The admin owns /nginx entirely; an upgrade only refreshes the nginx binary +# (handled by dpkg), the systemd unit, the nginx system user, and the log dir. +# +# Note: the empty /nginx skeleton is still part of the package payload, so dpkg +# keeps those dirs across upgrades without ever removing or rewriting them. This +# script deliberately performs ZERO operations on /nginx — no mkdir, no seed, +# no restore, no chown. + +set -e + +useradd -r -s /bin/false nginx 2>/dev/null || true + +# Log dir only — this is /var/log/nginx, NOT /nginx. +install -d -o nginx -g nginx -m 0755 /var/log/nginx +chown -R nginx:nginx /var/log/nginx 2>/dev/null || true + +systemctl daemon-reload 2>/dev/null || true +systemctl enable nginx.service 2>/dev/null || true +systemctl restart nginx.service 2>/dev/null || true + +exit 0 diff --git a/build/deb/preinst b/build/deb/preinst index d5a0c63..ca56e8f 100755 --- a/build/deb/preinst +++ b/build/deb/preinst @@ -1,5 +1,5 @@ #!/bin/sh -# preinst — shared by the twiy and twiy-raweb packages. +# preinst — twiy package ONLY (twiy-raweb uses preinst-raweb, a no-op). # # Older releases shipped /nginx as dpkg-tracked files. When upgrading from one # of those, dpkg deletes the old /nginx/* files during unpack (they are no diff --git a/build/deb/preinst-raweb b/build/deb/preinst-raweb new file mode 100755 index 0000000..26a7e9d --- /dev/null +++ b/build/deb/preinst-raweb @@ -0,0 +1,10 @@ +#!/bin/sh +# preinst — twiy-raweb package ONLY. +# +# STRICT RULE: this package MUST NOT touch /nginx in any way. There is nothing +# to back up or migrate because nothing under /nginx is ever read, written, or +# restored by twiy-raweb. Intentionally a no-op. + +set -e + +exit 0