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.
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;