Git keeps removing group write permissions - linux

I have a git repository that I am sharing with several developers. We do regular git pulls and pushes with it. Unfortunately, every time I do a git pull the changed files lose the group write permission. How do I stop git from doing this?
I am running this on Ubuntu 12.04 LTS.
The config on the shared repo looks like this:
[core]
repositoryformatversion = 0
filemode = true
bare = true
sharedRepository = group
I also ran the following commands on it in an attempt to fix it
find repo.git -type d -exec chmod g+rws {} +
sudo chmod -R g+rw repo.git/objects
No matter what I end up with folders with 755 and files with 644 when I want 775 and 664 respectively.

You should use the core.sharedRepository=group or core.sharedRepository=0664 setting.
See e.g. http://criticallog.thornet.net/2010/01/07/sharing-your-git-repository/

you can do this on a git hook with something like that:
#!/bin/sh
#
# .git/hooks/post-merge
sudo chmod -R g+rw *
it is called after every git pull, and file (.git/hooks/post-merge) must be executable

The users in question also need to have their umask set to 002.

Related

Failed to archieve Gitolite (Git) and nginx webserver access webspace at the same time

Starting point:
Ubuntu 20.04
Gitolite (/home/git/)
Webspace /var/www/webspace (usually owned by www-data:www-data)
Git user (in www-data group and also tried without beeing in group)
I want to update the webspace as git user with post-receive to a www-data directory. I had it archived before I installed Gitolite, but it doesn't seem to work the same way as it did before (or I am missing something). To make it clear: post-receive is executed after pushing (which it's normally not on Gitolite) ... was a hard time too to archive that.
Edit: To make it clear: I want to archive that Git and www-data can access and modify the same files.
What Ive tried:
chmod 777 -R /var/www/webspace (after this git can access but nginx returns with 403?)
Adding Git-User to www-data group
chown www-data:git -R /var/www/webspace
chown git:www-data -R /var/www/webspace
chown git:git -R /var/www/webspace
chown www-data:www-data -R /var/www/webspace (with and without git inside group)(with and without 777)
Executing post-receive manually (Operation not permitted)
Executing post-receive manually as root (well ... works of course, but thats not the point)
... maybe also some steps more which Im maybe missing rn
What Ive noticed so far:
On the contrary to Git, Gitolite checks the repo out with -rw------ (If i remember correctly), maybe that is why its not working with gitolite but with Git
The code (not that it would be important, but just to list everything):
post-receive
#!/bin/sh
GIT_WORK_TREE=/var/www/webspace git checkout -f
Maybe Im just missing something, but please help me.
Try and follow "adding other (non-update) hooks" in order for Gitolite to call the relevant post-receive hook.
add this line in the rc file, within the %RC block, if it's not already present, or uncomment it if it's already present and commented out:
LOCAL_CODE => "$ENV{HOME}/local",
put your hooks into that directory, in a sub-sub-directory called "hooks/common":
# log on to gitolite hosting user on the server, then:
cd $HOME
mkdir -p local/hooks/common
cp your-post-receive-hook local/hooks/common/post-receive
chmod +x local/hooks/common/post-receive
run gitolite setup to have the hooks propagate to existing repos (repos created after this will get them anyway).
Add user (git in my case) to group of webspace (www-data for me)
sudo usermod -a -G www-data git
If you were logged in as user logout to reload the group.
logout
#or
exit
#or
CTRL+A+D
(If you want to recheck the group login as this user and type "groups" to see the groups the user is in)
Make sure the webspace is owned by the correct group. For me:
sudo chown www-data:www-data -R /var/www/webspace
(If you want to recheck this you can go in the directory and type "ls -g")
In my case I had to modify my "post-receive" a bit, because the permissions were always -rw----- after checking out, so here is my "post-receive":
#!/bin/sh
GIT_WORK_TREE=/var/www/webspace git checkout -f #default line to checkout
chmod -R a+r /var/www/webspace #added by me because of permission issues
For convenience I had my "post-receive" in the repo directory (/home/git/repositories/repo/hooks/post-receive). The docs tell you to create a new folder (/home/git/local/specific-hooks/repo/post-receive (but they tell to name it on your own))
*All paths, names, groups and permissions written above only apply to me. They may differ for you installation.
What really solved my problem:
Logout after you change groups
Change permission (chmod) in post-receive

Subversion sudo svn update changes file ownership and rwx

I'm limiting permissions on a certain file, settings.py in my svn-linked directory so that it can only be read by sudo users and apache, which goes by the username, www-data. So, on settings.py, I've set sudo chmod 640 settings.py and sudo chown www-data:www-data settings.py. I still want my unprivileged users to be able to svn update and svn commit, so with sudo visudo, I've set
unprivileged_user ALL = /usr/bin/svn commit *, /usr/bin/svn update *, \
/usr/bin/svn update
so that this user can still do sudo svn commit and sudo svn update. It won't be able to do plain svn commit or svn update because of the limited permissions on settings.py. If the unprivileged user tries to do that, there will be a message from svn that says the working copy is locked. I've noticed however that when I do sudo svn update, the unprivileged_user is updating as root and as a result the file that are updated from the svn repository are now owned by root:root with 644 privileges. This goes against what I'm trying to with making settings.py owned by www-data:www-data. What can I do to make it so that www-data is always the owner and the rwx prvileges remain the same?
The www-data user will have a different UID on each system it is on, making it effectively a new user on each system. You cannot predict which user this will be so you cannot set the owner appropriately. Whoever checks it out will be the owner.
Furthermore, svn does not track permissions. It only tracks whether or not a file is executable. The permissions that the file comes with are determined by your umask.
Use an script instead which do the update and reset the permission.
svnupdate.sh:
#!/bin/bash
MY_PROJ_PATH=/home/.... # Put you path here
pushd $MY_PROJ_PATH
svn update $* && chown -R www-data. . && chmod 640 settings.py
popd
also make sure chmod 750 /usr/local/bin/svnupdate.sh to prevent security issue on sudo command
and also update the sudoeres files:
unprivileged_user ALL = /usr/bin/svn commit *, /usr/local/bin/svnupdate.sh
Here's what I have right now. I'm using a post svn update hook, and I don't know how secure it is. This is for svn update only. Please feel free to state your opinions on this.
In usr/local/bin, I create ssh-action.sh based off of this:
http://top-frog.com/2009/04/23/client-side-pre-and-post-svn-hooks-with-unix-aliases/
My actual ssh-action.sh looks like this:
#!/bin/bash
REAL_SVN='/usr/bin/svn';
BASE_PATH='/home/unprivileged_user/test_svn/';
$REAL_SVN $#;
wait;
# post-svn actions
if [ $1 = 'up' ] || [ $1 = 'update' ]; then
find -L $BASE_PATH -type f -name 'settings.py' -exec bash -c 'sudo chmod 0400 $0 && sudo chown www-data $0; sudo chgrp www-data $0' '{}' \;
fi
Then in sudo visudo, I add this to the bottom:
unprivileged_user ALL = NOPASSWD: /bin/chown www-data */test_svn/settings.py, /bin/chmod 0400 */test_svn/settings.py, /bin/chgrp www-data */test_svn/settings.py
Next, cd /home/unprivileged_user, open .bashrc , and add this to the bottom:
alias svn = /usr/local/bin/ssh-action.sh
Afterward, I need to make .bashrc immutable so that the unprivileged can't edit it to bypass my svn hook. I do this with sudo chattr +i .bashrc
With this hopefully whenever the unprivileged_user tries to svn update the test_svn working copy, settings.py will be owned by www-data:www-data with 400 permissions. What do you guys think? Are there any security flaws here? Thanks.

Setting umask with lftp in bash

I am trying to write a bash script to upload some files using lftp and need to set the umask to 002. I cant seem to figure out how this is done within the context of lftp.
lftp -c "open sftp://$STAGE_FTP_HOST
user $STAGE_FTP_USER $STAGE_FTP_PASS
cd web/content
mirror -P --only-newer --reverse --delete --verbose --exclude wp-content/uploads --exclude wp-content/cache --exclude .git* "
I have tried setting umask in /etc/pam.d/sshd, ~/.bashrc and /etc/ssh/sshd_config nothing has any effect.
To clarify I need to add group permission to files and folders on the remote machine. So instead of 755 i need 775 instead of 644 i need 664.
It seems like there is something specific to lftp that needs to be set that I am just completely missing.
lftp command chmod -R g+w . should do what you need (change permissions on the remote server).
For new uploads mirror --no-umask may also help, if local permissions are correct.

How to allow a group access for a GIT repo (Ubuntu)

So I have a GIT repo hosted with Gitosis.
I have a user called user1 and of course user root.
user1 belongs to group 'dev'
/var/www is owned by root, and grouped to 'dev'
permissions for the group are rwx
user1 has confirmed access to the git repo. I cloned it already and that works fine.
BUT, when I try to have user1 pull the repo on /var/www I get
error: cannot open .git/FETCH_HEAD: Permission denied
So what else am I missing. The GIT repo is already a --shared repo. For some reason I can't get this user to pull on /var/www ?
Thanks!
So turns out the answer was to change the GROUP of the .git folder to that of the user.
I hadn't realized that .git/FETCH_HEAD was a program and access was denied to run that. I thought it was a gitosis thing but it wasn't.
Thanks!
You can fix them retroactively (after which you won't need the config setting) with
chmod -R user:group /path/to/shared.git
find /path/to/shared.git -type d |xargs chmod 2775 # or 2770 if you don't want it public
find /path/to/shared.git -type f |xargs chmod 444 # or 440
find /path/to/shared.git/hooks |xargs chmod ugo+x # or ug+x

rsync over SSH preserve ownership only for www-data owned files

I am using rsync to replicate a web folder structure from a local server to a remote server. Both servers are ubuntu linux. I use the following command, and it works well:
rsync -az /var/www/ user#10.1.1.1:/var/www/
The usernames for the local system and the remote system are different. From what I have read it may not be possible to preserve all file and folder owners and groups. That is OK, but I would like to preserve owners and groups just for the www-data user, which does exist on both servers.
Is this possible? If so, how would I go about doing that?
** EDIT **
There is some mention of rsync being able to preserve ownership and groups on remote file syncs here: http://lists.samba.org/archive/rsync/2005-August/013203.html
** EDIT 2 **
I ended up getting the desired affect thanks to many of the helpful comments and answers here. Assuming the IP of the source machine is 10.1.1.2 and the IP of the destination machine is 10.1.1.1. I can use this line from the destination machine:
sudo rsync -az user#10.1.1.2:/var/www/ /var/www/
This preserves the ownership and groups of the files that have a common user name, like www-data. Note that using rsync without sudo does not preserve these permissions.
You can also sudo the rsync on the target host by using the --rsync-path option:
# rsync -av --rsync-path="sudo rsync" /path/to/files user#targethost:/path
This lets you authenticate as user on targethost, but still get privileged write permission through sudo. You'll have to modify your sudoers file on the target host to avoid sudo's request for your password. man sudoers or run sudo visudo for instructions and samples.
You mention that you'd like to retain the ownership of files owned by www-data, but not other files. If this is really true, then you may be out of luck unless you implement chown or a second run of rsync to update permissions. There is no way to tell rsync to preserve ownership for just one user.
That said, you should read about rsync's --files-from option.
rsync -av /path/to/files user#targethost:/path
find /path/to/files -user www-data -print | \
rsync -av --files-from=- --rsync-path="sudo rsync" /path/to/files user#targethost:/path
I haven't tested this, so I'm not sure exactly how piping find's output into --files-from=- will work. You'll undoubtedly need to experiment.
As far as I know, you cannot chown files to somebody else than you, if you are not root. So you would have to rsync using the www-data account, as all files will be created with the specified user as owner. So you need to chown the files afterwards.
The root users for the local system and the remote system are different.
What does this mean? The root user is uid 0. How are they different?
Any user with read permission to the directories you want to copy can determine what usernames own what files. Only root can change the ownership of files being written.
You're currently running the command on the source machine, which restricts your writes to the permissions associated with user#10.1.1.1. Instead, you can try to run the command as root on the target machine. Your read access on the source machine isn't an issue.
So on the target machine (10.1.1.1), assuming the source is 10.1.1.2:
# rsync -az user#10.1.1.2:/var/www/ /var/www/
Make sure your groups match on both machines.
Also, set up access to user#10.1.1.2 using a DSA or RSA key, so that you can avoid having passwords floating around. For example, as root on your target machine, run:
# ssh-keygen -d
Then take the contents of the file /root/.ssh/id_dsa.pub and add it to ~user/.ssh/authorized_keys on the source machine. You can ssh user#10.1.1.2 as root from the target machine to see if it works. If you get a password prompt, check your error log to see why the key isn't working.
I had a similar problem and cheated the rsync command,
rsync -avz --delete root#x.x.x.x:/home//domains/site/public_html/ /home/domains2/public_html && chown -R wwwusr:wwwgrp /home/domains2/public_html/
the && runs the chown against the folder when the rsync completes successfully (1x '&' would run the chown regardless of the rsync completion status)
Well, you could skip the challenges of rsync altogether, and just do this through a tar tunnel.
sudo tar zcf - /path/to/files | \
ssh user#remotehost "cd /some/path; sudo tar zxf -"
You'll need to set up your SSH keys as Graham described.
Note that this handles full directory copies, not incremental updates like rsync.
The idea here is that:
you tar up your directory,
instead of creating a tar file, you send the tar output to stdout,
that stdout is piped through an SSH command to a receiving tar on the other host,
but that receiving tar is run by sudo, so it has privileged write access to set usernames.
rsync version 3.1.2
I mostly use windows in local, so this is the command line i use to sync files with the server (debian) :
user#user-PC /cygdrive/c/wamp64/www/projects
$ rsync -rptgoDvhP --chown=www-data:www-data --exclude=.env --exclude=vendor --exclude=node_modules --exclude=.git --exclude=tests --exclude=.phpintel --exclude=storage ./website/ username#hostname:/var/www/html/website

Resources