From 46963cbeec0c306d3b33495a9c099b176163bca3 Mon Sep 17 00:00:00 2001 From: anti Date: Sun, 10 May 2026 01:26:13 -0400 Subject: [PATCH] fix(deployer): chown synced _caddy_modules back to source owner after root copy --- decnet/engine/deployer.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/decnet/engine/deployer.py b/decnet/engine/deployer.py index 2fd9d243..ba9a1295 100644 --- a/decnet/engine/deployer.py +++ b/decnet/engine/deployer.py @@ -166,6 +166,21 @@ def _sync_sessrec_sources(config: DecnetConfig) -> None: shutil.copy2(src, dest) +def _chown_tree(dest: Path, owner_ref: Path) -> None: + """Recursively set uid/gid of *dest* to match *owner_ref*. No-op if not root.""" + import os + if os.geteuid() != 0: + return + st = owner_ref.stat() + uid, gid = st.st_uid, st.st_gid + targets = [dest] + list(dest.rglob("*")) if dest.is_dir() else [dest] + for p in targets: + try: + os.lchown(p, uid, gid) + except OSError: + pass + + def _sync_caddy_modules(config: DecnetConfig) -> None: """Mirror _caddy_modules/ into http/https build contexts. @@ -200,9 +215,11 @@ def _sync_caddy_modules(config: DecnetConfig) -> None: if dest_child.exists(): shutil.rmtree(dest_child) shutil.copytree(child, dest_child) + _chown_tree(dest_child, src_dir) else: if not dest_child.exists() or dest_child.read_bytes() != child.read_bytes(): shutil.copy2(child, dest_child) + _chown_tree(dest_child, src_dir) def _compose_ps(compose_file: Path) -> list[dict[str, object]]: