DB-유

Using Synology as a Git Server

· synology, git, ssh

For a few private repositories I never wanted to pay for hosting or run a whole web application. Git only needs SSH and a directory of bare repos, and the NAS is always on and already backed up. Synology's Git Server package on DSM 6.2 installs the Git binaries and adds a small privilege dialog, and the rest is plain Git over SSH.

If you need pull requests, issues and a web UI, a Gitea container is the next step. This is the minimal version. You need the package installed, SSH enabled under Control Panel → Terminal & SNMP, and a shared folder for repos (mine is git, on Btrfs so snapshots cover it).

Users and Git access

Git users are ordinary DSM users. Create them under Control Panel → User and put them in a git-users group. Then open the Git Server package: it lists all users with a checkbox column "Allow access". Tick the ones who may use Git. Behind the scenes this sets their login shell so that they can run git-upload-pack and git-receive-pack over SSH but nothing else interactive.

Also give the git-users group Read/Write on the git shared folder (Control Panel → Shared Folder → Edit → Permissions).

Creating a bare repository

Over SSH as an administrator:

cd /volume1/git
sudo git init --bare --shared=group project-alpha.git
sudo chown -R root:git-users project-alpha.git
sudo chmod -R g+ws project-alpha.git

--shared=group sets core.sharedRepository=group, so objects written by one user remain writable by the others in the group, and the setgid bit keeps new directories in the group.

I forgot the chown step more than once and paid for it in permission errors, so now a small script does it:

#!/bin/bash
# /volume1/scripts/newrepo.sh <name>
set -e
REPO=/volume1/git/$1.git
git init --bare --shared=group "$REPO"
chown -R root:git-users "$REPO"
chmod -R g+ws "$REPO"
echo "ssh://$(hostname)/volume1/git/$1.git"

SSH keys

Password authentication over SSH works but I find it a poor fit for Git; typing it on every push gets old fast. Enable public key login: Control Panel → User → Advanced → Enable user home service must be on, then each user puts their key in place:

ssh-copy-id -p 22 jsmith@nas.example.local

On DSM the home directory permissions have to be tight or sshd ignores the key:

sudo chmod 755 /volume1/homes/jsmith
sudo chmod 700 /volume1/homes/jsmith/.ssh
sudo chmod 600 /volume1/homes/jsmith/.ssh/authorized_keys

If key login is still refused, check PubkeyAuthentication yes in /etc/ssh/sshd_config and restart SSH via Control Panel → Terminal & SNMP (untick and retick Enable SSH service).

Clone and push

On a workstation:

git clone ssh://jsmith@nas.example.local/volume1/git/project-alpha.git
cd project-alpha
echo "# Project Alpha" > README.md
git add README.md
git commit -m "Initial commit"
git push origin master

If you changed the SSH port in DSM, put it in the URL: ssh://jsmith@nas.example.local:2222/volume1/git/project-alpha.git. A ~/.ssh/config entry with Host nas and Port 2222 keeps URLs short.

Backups

Because repositories are files in a shared folder, Snapshot Replication (hourly snapshots on git) and Hyper Backup both cover them without extra work. For a consistent offsite copy I also mirror every repository nightly with a Task Scheduler script:

#!/bin/bash
for r in /volume1/git/*.git; do
  n=$(basename "$r")
  if [ -d "/volume1/backup/git/$n" ]; then
    git -C "/volume1/backup/git/$n" fetch --all --prune -q
  else
    git clone --mirror -q "$r" "/volume1/backup/git/$n"
  fi
done

Checking that it works

ssh jsmith@nas.example.local git --version
git ls-remote ssh://jsmith@nas.example.local/volume1/git/project-alpha.git

The first command should print the Git version from the package while an interactive ssh jsmith@nas login is refused with a message that the user is not allowed a shell. The second lists refs/heads/master after your push. On the NAS, ls /volume1/git/project-alpha.git/objects/ should show new object directories owned by the pushing user with the git-users group.

Errors you'll probably hit

  • fatal: '/volume1/git/project-alpha.git' does not appear to be a git repository: the user lacks Git access in the Git Server package or lacks shared folder permission; both look identical from the client.
  • error: insufficient permission for adding an object to repository database ./objects: the repository was created without --shared=group, or someone pushed as admin and created root-owned objects. Re-run the chown/chmod from the bare repository section.
  • Permission denied (publickey,password) with a key that works elsewhere: home folder permissions are too open (see the SSH keys section), or the user home service is disabled.
  • Pushing large repositories stalls at "Writing objects": the SSH session is being killed by an aggressive Auto Block rule or a firewall idle timeout. Whitelist the office IP under Control Panel → Security → Auto Block → Allow/Block List.

It has no web UI, and I don't miss it. One less thing to patch.