Merge claude/1
This commit is contained in:
commit
b2d57b2774
@ -2,87 +2,84 @@
|
||||
|
||||
# Mode-aware privileged operations.
|
||||
#
|
||||
# The privilege a file operation needs depends on the Docker mode:
|
||||
# rooted — app/container files under /docker are root-owned, so ops run via
|
||||
# sudo. This is byte-for-byte the historical behaviour.
|
||||
# rootless — those files are owned by the unprivileged Docker install user, so
|
||||
# ops run AS that user (via `sudo -u`, no root over the data plane).
|
||||
# Centralising the branch here means each call site is written once and is
|
||||
# correct in both modes, and rooted installs (incl. live boxes) are unchanged.
|
||||
# Ownership model (single source of truth — see reconcileDockerOwnership):
|
||||
# The MANAGER user ($sudo_user_name, e.g. libreportal) runs the CLI + host
|
||||
# scripts and is in the docker group, so it owns and operates the LibrePortal
|
||||
# control plane in BOTH modes. root:root is never the intended owner — it only
|
||||
# ever appeared as an artifact of un-de-sudo'd `sudo` commands.
|
||||
# rooted — the manager owns everything under /docker (it talks to the root
|
||||
# docker socket via the docker group); ops run AS the manager.
|
||||
# rootless — the manager owns the control plane; the docker install user owns
|
||||
# /docker/containers/** (the rootless daemon requires it).
|
||||
# Only genuine system administration (apt/systemctl/ufw/sysctl/useradd, /etc)
|
||||
# needs real root — that goes through runSystem.
|
||||
|
||||
# Run a /docker data-plane command — mkdir/chown/rm/cp/mv/find/sqlite3/etc. on
|
||||
# app or container files.
|
||||
# rooted -> sudo <cmd>
|
||||
# rootless -> run <cmd> as the Docker install user (no sudo)
|
||||
# Note: for stdin-fed writes (e.g. `… | sudo tee file`) use runFileWrite below;
|
||||
# this helper is for self-contained commands.
|
||||
# Run a command AS the manager user (plain if we're already it — the runtime
|
||||
# case — otherwise sudo -u to it, e.g. at install time when we're root). This is
|
||||
# how we keep files manager-owned instead of accidentally root-owned.
|
||||
runAsManager() {
|
||||
local mgr="${sudo_user_name:-libreportal}"
|
||||
if [[ "$(id -un)" == "$mgr" ]]; then
|
||||
"$@"
|
||||
else
|
||||
sudo -u "$mgr" "$@"
|
||||
fi
|
||||
}
|
||||
|
||||
# /docker data-plane command (mkdir/chown/rm/cp/mv/sed/sqlite3/docker/etc.) on
|
||||
# app/container files.
|
||||
# rooted -> as the manager user (owns /docker, in the docker group)
|
||||
# rootless -> as the docker install user (owns /docker/containers/**, and has
|
||||
# DOCKER_HOST set so `docker ...` hits the rootless socket)
|
||||
# For stdin-fed writes (`… | sudo tee file`) use runFileWrite below.
|
||||
runFileOp() {
|
||||
if [[ "$CFG_DOCKER_INSTALL_TYPE" == "rootless" ]]; then
|
||||
dockerCommandRunInstallUser --argv "$@"
|
||||
else
|
||||
sudo "$@"
|
||||
runAsManager "$@"
|
||||
fi
|
||||
}
|
||||
|
||||
# Write stdin to a path with the right privilege (replaces `… | sudo tee path`).
|
||||
# rooted -> sudo tee
|
||||
# rootless -> tee as the Docker install user
|
||||
# Pass -a/--append as the first arg to append instead of truncate (replaces
|
||||
# `… | sudo tee -a path`, e.g. the /docker/logs log-append idiom).
|
||||
# Write stdin to a /docker data-plane path (replaces `… | sudo tee path`).
|
||||
# Pass -a/--append as the first arg to append instead of truncate.
|
||||
# Usage: some_command | runFileWrite [-a] /path/to/file
|
||||
runFileWrite() {
|
||||
local append=""
|
||||
local append_flag=()
|
||||
if [[ "$1" == "-a" || "$1" == "--append" ]]; then
|
||||
append=" -a"
|
||||
append_flag=(-a)
|
||||
shift
|
||||
fi
|
||||
local dest="$1"
|
||||
if [[ "$CFG_DOCKER_INSTALL_TYPE" == "rootless" ]]; then
|
||||
dockerCommandRunInstallUser "tee$append '$dest' >/dev/null"
|
||||
dockerCommandRunInstallUser "tee ${append_flag[*]} '$dest' >/dev/null"
|
||||
else
|
||||
sudo tee$append "$dest" >/dev/null
|
||||
runAsManager tee "${append_flag[@]}" "$dest" >/dev/null
|
||||
fi
|
||||
}
|
||||
|
||||
# Genuine system-administration command (ufw/systemctl/apt/sysctl/useradd, /etc
|
||||
# edits). Needs real root in both modes; kept as sudo and funnelled through one
|
||||
# place so it can later be confined to a scoped sudoers allowlist.
|
||||
runSystem() {
|
||||
sudo "$@"
|
||||
}
|
||||
|
||||
# Op on a MANAGER-owned path — the LibrePortal clone + shipped templates AND the
|
||||
# /docker management layer the runtime owns (apps DB, configs/, logs/, scripts).
|
||||
# In rootless these are owned by the manager user; ops on them need no privilege.
|
||||
# rooted -> sudo <cmd> (root-owned; byte-identical)
|
||||
# rootless -> <cmd> (runs as the current user: root at install-time,
|
||||
# the manager user at runtime — both can access)
|
||||
# Container-owned data under /docker/containers/<app>/ is NOT this — use runFileOp.
|
||||
# For copies that read manager files and write container-owned ones, read here
|
||||
# and pipe into runFileWrite so each side runs as the correct owner.
|
||||
# Op on a MANAGER-owned path — the LibrePortal clone/templates AND the /docker
|
||||
# control plane (apps DB, configs/, logs/, scripts). Owned by the manager in
|
||||
# BOTH modes, so it always runs as the manager.
|
||||
runInstallOp() {
|
||||
if [[ "$CFG_DOCKER_INSTALL_TYPE" == "rootless" ]]; then
|
||||
"$@"
|
||||
else
|
||||
sudo "$@"
|
||||
fi
|
||||
runAsManager "$@"
|
||||
}
|
||||
|
||||
# Write stdin to a MANAGER-owned path (apps DB sidecars, configs/, logs/ — e.g.
|
||||
# the /docker/logs log-append idiom). Mirror of runFileWrite for the manager
|
||||
# owner. Pass -a/--append as the first arg to append.
|
||||
# rooted -> sudo tee
|
||||
# rootless -> tee as the current (manager) user
|
||||
# the /docker/logs log-append idiom). Manager-owned in both modes.
|
||||
# Pass -a/--append as the first arg to append.
|
||||
runInstallWrite() {
|
||||
local append=""
|
||||
local append_flag=()
|
||||
if [[ "$1" == "-a" || "$1" == "--append" ]]; then
|
||||
append=" -a"
|
||||
append_flag=(-a)
|
||||
shift
|
||||
fi
|
||||
local dest="$1"
|
||||
if [[ "$CFG_DOCKER_INSTALL_TYPE" == "rootless" ]]; then
|
||||
tee$append "$dest" >/dev/null
|
||||
else
|
||||
sudo tee$append "$dest" >/dev/null
|
||||
fi
|
||||
runAsManager tee "${append_flag[@]}" "$dest" >/dev/null
|
||||
}
|
||||
|
||||
# Genuine system-administration command (ufw/systemctl/apt/sysctl/useradd, /etc
|
||||
# edits). Needs real root in both modes; funnelled through one place so it can
|
||||
# later be confined to a scoped sudoers allowlist.
|
||||
runSystem() {
|
||||
sudo "$@"
|
||||
}
|
||||
|
||||
@ -43,14 +43,15 @@ reconcileDockerOwnership()
|
||||
done
|
||||
[[ -f "$docker_dir/$db_file" ]] && runSystem chmod o+r "$docker_dir/$db_file"
|
||||
|
||||
# LibrePortal's OWN WebUI container dir is regenerable and runs as 0:0
|
||||
# (root-in-container -> root rooted / install user rootless). Flip it to the
|
||||
# mode's container owner so the WebUI survives a switch; it's safe to recurse
|
||||
# because it's all one UID (no per-app uid to clobber). Third-party app data
|
||||
# elsewhere under containers/ is still left untouched.
|
||||
# LibrePortal's OWN WebUI container dir is regenerable, so flip it to the
|
||||
# mode's container owner so the WebUI survives a switch (safe to recurse —
|
||||
# it's all one UID, no per-app uid to clobber). Third-party app data
|
||||
# elsewhere under containers/ is left untouched.
|
||||
# rooted -> the manager (it owns everything under /docker in rooted)
|
||||
# rootless -> the docker install user (owns /docker/containers/**)
|
||||
local webui_dir="${containers_dir}libreportal"
|
||||
if [[ -d "$webui_dir" ]]; then
|
||||
local app_owner="root"
|
||||
local app_owner="$owner"
|
||||
[[ "$mode" == "rootless" ]] && app_owner="$docker_install_user"
|
||||
runSystem chown -R "$app_owner:$app_owner" "$webui_dir"
|
||||
fi
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user