For 2 days, I had to deal with a repository in one of my jobs. It was a production repo
that, over time of poor maintenance, had been in the ownership of root user. This is not ideal because you don't want a folder used by webserver to be owned by root. It's a
security nightmare, and it is hard to pull code with git. I constantly had to use sudo.
Solving with ACL
When dealing with this problem on the production server, I had a different development server, set up to closely match the deployment of the production. As I navigated through the difference between the two servers' repos to determine the cause of the problem, I found that:
- They both are owned by
root:root. But the dev one could be updated withgit pullwhile the prod one I had tosudo git pull - The dev one has a hidden ACL list. Normally, a folder when typed in
getfaclshows this:
user::rwx
group::r-x
other::--x
while the dev repo showed:
user::rwx
group::r-x
group:padmins:rwx
mask::rwx
other::r-x
Notice padmins. My user was part of that group, which explained why I could pull the
code from the remote repo. I tried setting ACL rules on the prod's repo but failed. It said
that it couldn't run setfacl successfully. Turns out, the web was served from a network
drive, so most likely the protocol didn't support ACL.
Solving with user:group
I tried a different approach. I changed specific folders that tend to have changes instead of all the repo because I didn't want to cause a fuss. I learned a couple of lessons:
- Getting git to show verbose logs can be done via
GIT_TRACE=1 GIT_TRACE_PERFORMANCE=1 git <command>. - You need to change ownership of
.gitif you want any command of git to work. I was trying to stash a change, and it kept denying. Not only that, the uncommitted files and folders containing them need to have permissions to be unlinked, too. So those containing folders need their permission set to either644(rw-r--r--),664(rw-rw-r) or775(rwxrwxr-x) and with your user:group ownership. You need write permission on the directory containing it, not on the file itself. - Be cautious when changing permission relating to your user. The table below shows what git records when you commit a change. You can verify what git thinks with
git ls-files -s <file>. This command shows what's in git's index. git doesn't care about ownership, which is the angle I used to change the repo so I could easily pull changes without sudo.
| Github Mode | Actual Mode | Meaning |
|---|---|---|
| 100644 | 6xx | Non-executable file |
| 100755 | 7xx | Executable file |
| 120000 | Symbolic link |
- Even if I set the folder's permission, I kept losing the group write bit. I discovered
that
umaskwas set to0022, which always unset the group write bit. I have to set it back toumask 0002. What each umask bit represents:- First Digit (0): Special permissions like SUID, SGID, or the sticky bit. In most umask contexts, this is simply a leading zero and has no effect on standard creation.
- Second Digit (0): Permissions for the User (Owner). 0 means no permissions are removed (the owner keeps full access).
- Third Digit (2): Permissions for the Group. 2 means write access is removed.
- Fourth Digit (2): Permissions for Others. 2 means write access is removed.
- You actually need execution permission bit (x) for a directory in order to enter
or
cdit. The system treats this bit as search permission. Best to set the permission as775(normal permission for most users).