feat: add .apex-root-owned opt-out for root-owned tier compositions

An empty .apex-root-owned marker in a composition dir makes tiers/useradd
skip its noroot user + .env UID injection, and tiers/chown force its tier
data (dir + children, recursively) to root:root instead of noroot-<proj>.
For services that run as root and reject non-root-owned data (e.g. seafile-mc).
This commit is contained in:
deytenit committed 2026-07-06 10:39:04 +03:00
1 parent 0b42ab1bfc
commit 334ca196e0
2 files changed
+16

No files matched your search

+10
View File
@@ -46,6 +46,16 @@ def run(ctx, args):
full = os.path.join(comp, proj)
if not os.path.isdir(full) or proj.startswith(".") or proj.startswith("@"):
continue
# opt-out: .apex-root-owned forces this project's tier data (dir + children,
# recursively) to root:root — for services that run as root and reject
# non-root-owned data (e.g. seafile-mc). Blocks noroot ownership entirely.
if os.path.isfile(os.path.join(full, ".apex-root-owned")):
log.info(f"Applying root ownership for {proj} (.apex-root-owned)")
for tp in tiers:
for d in (os.path.join(tp, proj), os.path.join(tp, "shared", proj)):
if os.path.isdir(d):
s.sudo(["chown", "-R", "root:root", d]); log.success(f" Owned {d} (root)")
continue
env_path = os.path.join(full, ".env")
uid = _env_val(env_path, "APEX_UID")
gid = _env_val(env_path, "APEX_GID")
+6
View File
@@ -34,6 +34,12 @@ def run(ctx, args):
full = os.path.join(comp, proj)
if not os.path.isdir(full) or proj.startswith(".") or proj.startswith("@"):
continue
# opt-out: a project marked .apex-root-owned runs as root and keeps its tier
# data root-owned (e.g. seafile-mc, whose entrypoint refuses non-root-owned
# data). Skip the noroot user + .env UID injection; tiers/chown forces root.
if os.path.isfile(os.path.join(full, ".apex-root-owned")):
log.info(f"{proj}: .apex-root-owned — runs as root; skipping noroot user")
continue
base = f"noroot-{_sanitize(proj)}"
cand, i = base, 1
while cand in used: