grafana/prometheus: permission the directory, not the container's files
Both apps ran `chmod -R 777` over their data dirs in install_post_start —
after the container has booted and written files as its own uid (grafana
472 -> host subuid 231543, prometheus nobody 65534 -> 296605). chmod by a
non-owner fails, so every REINSTALL printed "Operation not permitted" per
file and failed the step; a fresh install passed only because the dir was
still empty when it ran. Reproduced on a live install of both.
The permission is only needed on the DIRECTORY, so the container can
create its store on first boot. What it creates after that is its own and
must stay that way — chowning or chmod'ing it away is what would actually
break these apps. So: non-recursive 0777 on grafana_storage and prom_data.
prometheus's config dir is a separate case — the container only READS it —
so it gets a+rX,go-w instead. The go-w matters: a+rX only adds bits, so
without it prometheus.yml stays world-writable on every install the old
777 already touched, and prometheus obeys that file. Everything there is
written through runFileOp, i.e. by the owner, so owner-write is enough.
updateFileOwnership used `runSystem chown`, but the scoped sudoers grants
the manager root only for the fixed LibrePortal helpers and
systemctl/ufw/nft/sysctl — never a bare chown, which would be
root-equivalent. It was denied on every call ("I'm sorry libreportal"),
printing a red ✗ Error on every prometheus install, and its message
referenced an undefined $user_name so it read "with ownership". Use
runFileOp (runs as the owner of the data plane) and name the user.
Verified live: prometheus and grafana both installed fresh and reinstalled
with 0 errors; prometheus.yml went 0777 -> 0755 with prometheus still
healthy (200); grafana serving 200; grafana.db and prom_data/data keep
their container uids.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
6cc604f21f
commit
5c7372b8c2
@ -15,9 +15,16 @@ grafana_install_pre()
|
||||
grafana_install_post_start()
|
||||
{
|
||||
local app_name="$1"
|
||||
# The DIRECTORY, not its contents. Grafana runs as uid 472, which rootless
|
||||
# maps to a subuid this user has no authority over; it needs write on the dir
|
||||
# itself to create grafana.db and its plugin/png dirs on first boot, and from
|
||||
# then on those files are its own. `chmod -R` walked them as the docker
|
||||
# install user and failed per file with "Operation not permitted", failing the
|
||||
# step on every reinstall — while a fresh install passed, because the dir was
|
||||
# still empty. Grafana's files must keep Grafana's ownership regardless.
|
||||
if [ -d "${containers_dir}grafana/grafana_storage" ]; then
|
||||
local result
|
||||
result=$(runFileOp chmod -R 777 "${containers_dir}grafana/grafana_storage")
|
||||
result=$(runFileOp chmod 0777 "${containers_dir}grafana/grafana_storage")
|
||||
checkSuccess "Set permissions to grafana_storage folder."
|
||||
fi
|
||||
}
|
||||
|
||||
@ -26,14 +26,36 @@ prometheus_install_post_start()
|
||||
if [ -f "${containers_dir}prometheus/prometheus/prometheus.yml" ]; then
|
||||
updateFileOwnership "${containers_dir}prometheus/prometheus/prometheus.yml" $docker_install_user $docker_install_user
|
||||
fi
|
||||
# Prometheus runs as nobody (65534) inside the container, which rootless maps
|
||||
# to a subuid outside this user's authority (65534 -> 296605 here). Two
|
||||
# different needs, and the old blanket `chmod -R 777` on both got the second
|
||||
# one wrong:
|
||||
#
|
||||
# prometheus/ config, READ-only to the container. a+rX is enough — world
|
||||
# WRITE on a config the container obeys is not something to
|
||||
# hand out, and -R is safe here because nothing but LibrePortal
|
||||
# writes this dir. go-w is included so the fix actually lands on
|
||||
# installs the old 777 already touched: a+rX only ADDS bits, so
|
||||
# without it every existing prometheus.yml stays world-writable
|
||||
# by any local user. Everything here is written through
|
||||
# runFileOp — i.e. by the owner — so owner-write is all it needs.
|
||||
#
|
||||
# prom_data/ the container's own store. It needs write on the DIRECTORY to
|
||||
# create prom_data/data on first boot; everything under that is
|
||||
# created by, and belongs to, prometheus itself. Recursing into
|
||||
# it meant chmod'ing files owned by 296605 as the docker install
|
||||
# user: "Operation not permitted" per file and a failed step on
|
||||
# every REINSTALL (a fresh install passed only because the dir
|
||||
# was still empty). Those files must keep prometheus's ownership
|
||||
# anyway — that is what lets it write them.
|
||||
if [ -d "${containers_dir}prometheus/prometheus" ]; then
|
||||
local result
|
||||
result=$(runFileOp chmod -R 777 "${containers_dir}prometheus/prometheus")
|
||||
result=$(runFileOp chmod -R a+rX,go-w "${containers_dir}prometheus/prometheus")
|
||||
checkSuccess "Set permissions to prometheus folder."
|
||||
fi
|
||||
if [ -d "${containers_dir}prometheus/prom_data" ]; then
|
||||
local result
|
||||
result=$(runFileOp chmod -R 777 "${containers_dir}prometheus/prom_data")
|
||||
result=$(runFileOp chmod 0777 "${containers_dir}prometheus/prom_data")
|
||||
checkSuccess "Set permissions to prom_data folder."
|
||||
fi
|
||||
}
|
||||
|
||||
@ -1,13 +1,25 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Set owner:group on a single file under the data plane.
|
||||
#
|
||||
# runFileOp, not runSystem: the scoped sudoers grants the manager root for the
|
||||
# fixed LibrePortal helpers and systemctl/ufw/nft/sysctl only — never a bare
|
||||
# `sudo chown`, since that is root-equivalent (chown /etc/sudoers). `runSystem
|
||||
# chown` therefore could not succeed on any correctly-installed system; it was
|
||||
# denied every time, and because the result feeds checkSuccess it printed a red
|
||||
# ✗ Error on every prometheus install. runFileOp runs as the owner of the data
|
||||
# plane (the docker install user under rootless, the manager under rooted), which
|
||||
# is exactly who may set these.
|
||||
#
|
||||
# Ownership that genuinely needs root — establishing the /docker model, reclaiming
|
||||
# a root-owned file — belongs in the libreportal-ownership helper instead.
|
||||
updateFileOwnership()
|
||||
{
|
||||
local file="$1"
|
||||
local file_name=$(basename "$file")
|
||||
local clean_dir=$(echo "$file" | sed 's#//*#/#g')
|
||||
local user_name_1="$2"
|
||||
local user_name_2="$3"
|
||||
|
||||
local result; result=$(runSystem chown $user_name_1:$user_name_2 "$file")
|
||||
checkSuccess "Updating $file_name with $user_name ownership"
|
||||
local result; result=$(runFileOp chown "$user_name_1:$user_name_2" "$file")
|
||||
checkSuccess "Updating $file_name with $user_name_1 ownership"
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user