LibrePortal/containers/prometheus/scripts/prometheus_install_hooks.sh
librelad 5c7372b8c2 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>
2026-08-18 23:39:44 +01:00

62 lines
3.0 KiB
Bash

#!/bin/bash
# Prometheus install hooks — drop the prometheus.yml template alongside the
# compose, and 0777 the storage dirs so the container can write its TSDB
# regardless of the host UID mapping.
prometheus_install_post_compose()
{
local app_name="$1"
local result
result=$(createFolders "loud" $docker_install_user "$containers_dir$app_name/$app_name")
checkSuccess "Created $app_name folder in $app_name"
result=$(createTouch "$containers_dir$app_name/$app_name/$app_name.yml" $docker_install_user)
checkSuccess "Created $app_name.yml file for $app_name"
result=$(copyResource "$app_name" "$app_name.yml" "$app_name" | runInstallWrite -a "$logs_dir/$docker_log_file" 2>&1)
checkSuccess "Copying $app_name.yml to containers folder."
}
prometheus_install_post_start()
{
local app_name="$1"
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 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 0777 "${containers_dir}prometheus/prom_data")
checkSuccess "Set permissions to prom_data folder."
fi
}