mcp: session-notes — ACL fix for shared git repos under /opt/projects
This commit is contained in:
parent
16af944861
commit
ec93dd28dc
56
Sources/Homelab/2026-05-18-acl-shared-repo-permissions.md
Normal file
56
Sources/Homelab/2026-05-18-acl-shared-repo-permissions.md
Normal file
@ -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
|
||||
Loading…
Reference in New Issue
Block a user