Monday, October 13, 2014

Seagate GoFlex Home NAS - Git server installation

While quite comfortable with SVN and happy with the previous SVN server installation on the Seagate GoFlex Home NAS, I'd like to take things a bit further and try out a Git server. Some of the things looking forward to are local commits while away or when the NAS is sleeping, and pushing those changes at a later stage when connected. So, here we go.

Prerequisites


See previous post where we installed ipkg (will use it to install the Git software) and we setup a system account for HDD storage (will use it to store the Git repositories).

Git software


bash-3.2# ipkg install git
Installing git (1.8.4.2-1) to root...
Downloading http://ipkg.nslu2-linux.org/feeds/optware/cs08q1armel/cross/stable/git_1.8.4.2-1_arm.ipk
package git suggests installing git-manpages
Configuring git
Successfully terminated.

bash-3.2# git --version
git version 1.8.4.2

Git user group


Creating a user group called git to which will add user apache (see later section) and to which will give write access to the repositories, or you could use to add real users to if you want to use ssh and real users for access.
bash-3.2# groupadd git
bash-3.2# usermod -a -G git apache
bash-3.2# id apache
uid=48(apache) gid=48(apache) groups=48(apache),100(users),500(www),104(fuse),508(git)

Git repositories


Preparing the location to store the git repositories and will create a firs repository called MyProject.git. You can create another level inside repos to group your applications, e.g. mobile or android, and then create repositories inside that.
bash-3.2# mkdir -p /home/0loop0/srv/git/
bash-3.2# ln -sv /home/0loop0/srv/git/ /srv/
create symbolic link `/srv/git' to `/home/0loop0/srv/git/'

bash-3.2# cd /srv/git
bash-3.2# df -h .
Filesystem            Size  Used Avail Use% Mounted on
/dev/loop0            985M  150M  785M  17% /home/0loop0

bash-3.2# mkdir repos
bash-3.2# chgrp git repos
bash-3.2# chmod g+ws repos
bash-3.2# ls -ld repos
drwxrwsr-x 2 root git 4096 Oct 13 12:58 repos

bash-3.2# cd repos
bash-3.2# git init --bare MyProject.git
Initialized empty Git repository in /home/0loop0/srv/git/repos/MyProject.git/
bash-3.2# chmod -R g+w .

 

Git server (http://)

 

There are a few protocols to choose from and while at first I was going go to do ssh:// for security, that looked a bit more complicated and the fact that Seagate GoFlex Home NAS requires those long SSH usernames including the serial number, I decided to go for unsecured HTTP access as after all most of us do not expose this over the internet and you're probably the only user that knows about it :-), although you could go further and secure it yourself through HTTP basic authentication.

Edit /etc/httpd/conf/httpd.conf to add the lines below:
#
# Git
#
SetEnv GIT_PROJECT_ROOT /srv/git/repos/
SetEnv GIT_HTTP_EXPORT_ALL
SetEnv REMOTE_USER $REDIRECT_REMOTE_USER

ScriptAlias /git/ /opt/libexec/git-core/git-http-backend/

<Location "/git">
    AuthType None
    Require all granted
    Satisfy Any
</Location>
Restart web service:
bash-3.2# service httpd restart
Stopping httpd:                                            [  OK  ]
Starting httpd:                                            [  OK  ]

From a client machine take the project down and try a first commit (using GitHub's GitShell on Windows here):
R:\temp> git clone http://goflex_home/git/MyProject.git
Cloning into 'MyProject'...
warning: You appear to have cloned an empty repository.
Checking connectivity... done.

R:\temp>cd MyProject

R:\temp\MyProject [master]> echo "contents" > first.txt

R:\temp\MyProject [master +1 ~0 -0 !]> git add first.txt

R:\temp\MyProject [master +1 ~0 -0]> git commit -m "First commit"
[master (root-commit) 8db2238] First commit
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 first.txt 

R:\temp\MyProject [master]> git push
Counting objects: 3, done.
Writing objects: 100% (3/3), 231 bytes | 0 bytes/s, done.
Total 3 (delta 0), reused 0 (delta 0)
To http://goflex_home/git/MyProject.git
 * [new branch]      master -> master 

Git backup


Similar to previous SVN post, you probably want to backup the git repositories regularly so we're going to use our own system GoFlex Home Backup location for it.

First we'll create the script to backup a single repository:
bash-3.2# cd /srv/git
bash-3.2# cat > git-backup << EOL
#!/bin/bash

if [ -z "\$1" ]; then
  echo -e "Usage:\n   \$0 repository-name"
  exit 99
fi

GIT_REPOS_DIR=/srv/git/repos/
GIT_BACKUP_DIR=/home/system/GoFlex\ Home\ Backup/git/
GIT_BACKUP_FILE=\$1.git-bundle-\$(date +"%Y%m%d-%H%M%S")
KEEP_DAYS=31

echo -e "\n*** (1/5) Creating temporary clone..."
cd "\$GIT_BACKUP_DIR"
git clone "\$GIT_REPOS_DIR/\$1"

echo -e "\n*** (2/5) Creating bundle..."
cd "\$1"
git bundle create "../\$GIT_BACKUP_FILE" --all

echo -e "\n*** (3/5) Verifying bundle..."
git bundle verify "../\$GIT_BACKUP_FILE"

echo -e "\n*** (4/5) Deleting temporary clone..."
cd "\$GIT_BACKUP_DIR"
rm -rf "\$1"

echo -e "\n*** (5/5) Trimming backups - older than \$KEEP_DAYS days..."
find "\$GIT_BACKUP_DIR" -name "\$1.git-bundle-*" -mtime +\$KEEP_DAYS -exec ls {} \; -exec rm {} \;
EOL

bash-3.2# chmod a+x git-backup
Now create the backup location:
bash-3.2# mkdir "/home/system/GoFlex Home Backup/git/"
With that done, we're ready for a test:
bash-3.2# /srv/git/git-backup MyProject
*** (1/5) Creating temporary clone...
Cloning into 'MyProject'...
done.

*** (2/5) Creating bundle...
Counting objects: 6, done.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (6/6), 461 bytes | 0 bytes/s, done.
Total 6 (delta 0), reused 0 (delta 0)

*** (3/5) Verifying bundle...
The bundle contains these 4 refs:
9a0f0ff039cb631ce62218e39d976015c8a6778b refs/heads/master
9a0f0ff039cb631ce62218e39d976015c8a6778b refs/remotes/origin/HEAD
9a0f0ff039cb631ce62218e39d976015c8a6778b refs/remotes/origin/master
9a0f0ff039cb631ce62218e39d976015c8a6778b HEAD
The bundle records a complete history.
../MyProject.git-bundle-20141013-151323 is okay

*** (4/5) Deleting temporary clone...

*** (5/5) Trimming backups - older than 31 days...
Finally, we can add the job to run daily:
bash-3.2# cat > /etc/cron.d/git-backup << EOL
0 22 * * * root /srv/git/git-backup MyProject
EOL
The end.