Search code examples
gitsynology

Problems pushing a new repo to Synology git server


I have recently set up git on a Synology NAS (DS2220j if that makes any difference) and have successfully set up things like using public keys etc, and can push updates to a repository that exists on the Synology server itself.

My setup is that my own user on the Synology drive has a git directory in its home directory. I run the following to create a repo:

ssh user@NAS
cd git
git init --bare repo.git

I can then run locally

cd repo
git remote add origin user@NAS:git/repo.git
git push --set-upstream origin master

and this will push my repo to the git server fine. My problem is that I want to be able to skip the initial step where I ssh into the Synology drive, as I don't actually want to be able to directly ssh into an interactive shell as my user. If I skip this step however, I get the following output:

fatal: 'git/repo.git' does not appear to be a git repository
fatal: Could not read from remote repository.

Please make sure you have the correct access rights and the repository exists.

On some git servers there is a line in the config to allow pushing fresh repos, but I can't see any documentation for the server included in the Synology package centre (which is what I'm using) and various tutorials show it just working. One tutorial showed creating a bare _template.git in the folder where you wish to push repos, which I've tried, but that doesn't seem to have any effect.


Solution

  • You can completely control what a user/key combo is allowed to do by setting up that user's ~/.ssh/authorized-keys file for that key. Put

    command="bin/checkcommand" ssh-ed25519 AAAAC3NklC1wZDI1NTE5AAAAIH5NBbarfcodeFWkCC6KKU8qYLBNpnYWXHpxwcTKBesu you@example.com
    

    in it and whenever you sign on as that user with that key their bin/checkcommand will run with SSH_ORIGINAL_COMMAND set to whatever was on the ssh command line, so you'll have to basically do some simple command parsing to permit evengit-upload-pack and git-receive-pack if you want them able to fetch or push.

    Say man sshd and search for command= for the starter kit I'm cribbing from, I haven't checked but I'd bet money gitolite and so on use exactly this mechanism.

    bin/checkcommand might look a little like this, but with a whitelist of commands it will run, rather than running whatever you throw at it:

    #!/bin/bash -e
    set -o pipefail;
    
    echo command="${SSH_ORIGINAL_COMMAND}" >> ~/.ssh/log; 
    
    # Up to the first space is the command
    case $(echo "${SSH_ORIGINAL_COMMAND}" | cut -f 1 -d ' ') in
        "git-receive-pack" | "git-upload-pack")
            # Second part is the git directory, contained within quotes
            GITDIR="$( \
                echo "${SSH_ORIGINAL_COMMAND}" \
                    | cut -f 2- -d " " \
                    | cut -f 2 -d "'" \
            )";
            echo "git at ${GITDIR}" >> ~/.ssh/log;
    
            if [ ! -d ${GITDIR} ]; then
                git init --bare ${GITDIR} 2>&1 >> ~/.ssh/log;
            fi
        ;;  
    esac
    
    bash -c "${SSH_ORIGINAL_COMMAND}" | tee -a ~/.ssh/log;