From ec93dd28dcdadb14604186732840610e9018bf1a Mon Sep 17 00:00:00 2001 From: Lovebug MCP Date: Mon, 18 May 2026 22:25:46 +0000 Subject: [PATCH] =?UTF-8?q?mcp:=20session-notes=20=E2=80=94=20ACL=20fix=20?= =?UTF-8?q?for=20shared=20git=20repos=20under=20/opt/projects?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../2026-05-18-acl-shared-repo-permissions.md | 56 +++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 Sources/Homelab/2026-05-18-acl-shared-repo-permissions.md diff --git a/Sources/Homelab/2026-05-18-acl-shared-repo-permissions.md b/Sources/Homelab/2026-05-18-acl-shared-repo-permissions.md new file mode 100644 index 0000000..08a9df3 --- /dev/null +++ b/Sources/Homelab/2026-05-18-acl-shared-repo-permissions.md @@ -0,0 +1,56 @@ +--- +created: '2026-05-18' +path: Sources/Homelab +project: herbys-dev-setup +tags: +- git +- ssh +- automation +type: session-notes +--- + +## Outcome + +Resolved a recurring permissions issue where `herbyadmin` (Claude Code / Lovebug operating account) couldn't write to git repo files under `/opt/projects` after `travadmin` (GitHub SSH push/pull account) ran `git pull`. Applied POSIX default ACLs to `/opt/projects` so both users get explicit `rwX` on everything in the tree — current and future. + +## Topics Covered + +- Shared git repo across two users (`herbyadmin` + `travadmin`) under `/opt/projects` +- Why setgid on directories wasn't enough — `git pull` uses atomic rename, which bypasses setgid inheritance +- `core.sharedRepository = group` vs. file ownership — separate concerns +- POSIX ACLs (`setfacl` / `getfacl`) as the durable fix +- Access ACL vs. default ACL — default propagates to anything newly created + +## Key Learnings + +- **Setgid alone doesn't survive `git pull`.** Git creates pack files in a temp location and renames them in. `mv` preserves the original group; it doesn't re-apply the parent directory's setgid. Result: files land with the pulling user's primary group, not the project group. +- **`core.sharedRepository = group` is necessary but not sufficient.** It makes git write group-writable files (mode bits), but doesn't control which group owns them. +- **Default ACLs are the right tool for shared trees.** They sit alongside traditional ownership, grant access independently, and propagate automatically to new files regardless of which user, umask, or rename trick created them. +- **`rwX` (capital X) means "execute on directories only."** Cleaner than `rwx` for ACL templates — files don't get a stray execute bit, directories still get traversal. + +## The Pattern + +Applied once to `/opt/projects`: + +``` +sudo setfacl -R -m u:herbyadmin:rwX,u:travadmin:rwX,g:devprojects:rwX \ + -m d:u:herbyadmin:rwX,d:u:travadmin:rwX,d:g:devprojects:rwX \ + /opt/projects +``` + +- `-R` — recursive over existing files +- `-m` — modify (add ACL entries) +- `d:` prefix — default ACL, inherited by new files/dirs +- Both users + the group get explicit access, so any ownership combination still works + +To add a future user/service account: + +``` +sudo setfacl -R -m u:newuser:rwX -m d:u:newuser:rwX /opt/projects +``` + +## Follow-ons + +- [ ] Verify the ACL pattern survives a few real `git pull` / `git commit` cycles from both users +- [ ] Consider adding `setfacl` step to the Ansible role for `herbys-dev-setup` so any new dev VM gets the same shared-repo permissions baked in +- [ ] If a third agent account (e.g., a CI runner) ever needs repo access, extend the ACL rather than juggling group memberships \ No newline at end of file