Keeping in line with my policy of low memory overhead, I do not want to waste several hundred megabytes on a git repository manager, such as Gitlab or Bitbucket. If you get back to Git basics, you can set up a Git repository with no additional overhead.
Basics
Let’s get back to basics, what is Git? Git is a distributed version control system, which means it’s just a bunch of files on disk. Git is fairly protocol-agnostic, so it can transfer data over HTTP, FTP or the Git protocol. Often, the Git protocol is used in conjunction with ssh, which handles the transport layer encryption and authentication. Whenever you see a command line git clone git@git:repo, you are most likely using Git+SSH.
This guide assumes you know how SSH public-private key authentication works. If not, follow this tutorial on Digital Ocean.
Setup
Git+SSH
To set up a Git+SSH server, so you can clone/commit etc. via SSH is fairly simple. Create a single Unix user, through which all users will authenticate based on their password. To make it a bit more user-friendly and secure, do the following steps:
-
Create a Git user.
groupadd git useradd -g git -m -d /srv/git -s /usr/bin/git-shell -c "Git User" gitThere are several aspects which are important in this command:
-
-m -d /srv/gitThis creates a home directory for thegituser which will store all the repositories. Since you can use relative paths with SSH, this allows you to put a repository in/srv/git/repo1and clone it withgit clone [email protected]:repo1. No need to use full paths. -
-s /usr/bin/git-shellis a purpose built shell for Git use only. Remember, SSH normally grants you a login shell, which allows you to do everything on a system what a non-root user can, which is a lot! Thegit-shellonly allows clients to execute Git related commands.
Tip: You might need to add
/usr/bin/git-shellto the list of allowed shells (often found at/etc/shells) to allow logins usinggit-shell. This depends on your distribution. -
-
Make sure the
gituser home directory is owned by thegituser:chown git: /srv/git -
Add public keys for the users to the
gituser’sauthorized_keys file:mkdir /srv/git/.ssh chmod 700 /srv/git/.ssh echo 'ssh-rsa AAAAB3NzaC1yc2EAA...ZGXMchiG0K4aNp5= [email protected]' >> /srv/git/.ssh/authorized_keys chmod 600 /srv/git/.ssh/authorized_keys chown -R git: /srv/git/.sshMake sure you end up with the following permissions:
drwx------ 2 git git 4096 nov 23 2015 .ssh -rw------- 1 git git 218 nov 23 2015 .ssh/authorized_keysTip: if you have problems logging on using Git, test if you can log on with a normal SSH client. Make sure the permissions for the
.ssh/directory andauthorized_keysfile exactly match the ones stated above. -
Create a Git repository on the server. You need to create a ‘bare’ Git repository to allow operations over SSH.
cd /srv/git git init --bare repoName chown -R git: repoName -
Clone and work with the repo!
You can now work with the repository by using the git remote [email protected]:repoName, for example with:
git clone [email protected]:repoName
git remote add origin [email protected]:repoName
HTTP Browsing
So now we have a basic Git server running, we can enhance it a bit by allowing read-only HTTP browsing of the repositories for easy access. Since I already have an Apache HTTP server with PHP running, I decided to use GitList. The stable GitList version at time of writing is 0.5.0.
-
Download GitList
wget https://s3.amazonaws.com/gitlist/gitlist-0.5.0.tar.gz -
Untar it in your webroot or other directory which is accessible by your webserver
cd /var/www/ tar -zxvf /home/user/Downloads/gitlist-0.5.0.tar.gz -
Copy the
config.ini-examplefile toconfig.iniand change the following parameters:[git] repositories[] = '/srv/git'; [date] timezone = 'Europe/Amsterdam' -
Make sure the Git repository directory is readable by the webserver user. The easiest way to do this is by adding the webserver user to the
gitUnix group:usermod -G git www-data -
Browse to the GitList page (probably at http://git.example.com/gitlist/)
-
Optionally, add authentication and SSL. Use this Apache config as a guide:
<VirtualHost 192.0.2.10:443> ServerAdmin admin@git.example.com ServerName git.example.com DocumentRoot /var/www/gitlist/ SSLEngine on SSLProtocol all -SSLv2 SSLCipherSuite ALL:!ADH:!EXPORT:!SSLv2:RC4+RSA:+HIGH:+MEDIUM SSLCertificateFile /etc/apache2/ssl/git.example.com.crt SSLCertificateKeyFile /etc/apache2/ssl/git.example.com.key SSLCACertificateFile /etc/apache2/ssl/git.example.com_ca.crt ErrorLog ${APACHE_LOG_DIR}/git.example.com_error.log CustomLog ${APACHE_LOG_DIR}/git.example.com_access.log combined LogLevel warn <Directory /var/www/gitlist> Options MultiViews FollowSymLinks AllowOverride all Order allow,deny allow from all AuthName "GitList" AuthType Basic AuthBasicProvider ldap AuthLDAPURL ldap://ldap.example.com/dc=example,dc=com?uid AuthLDAPGroupAttribute memberUid AuthLDAPGroupAttributeIsDN off Require ldap-group cn=git,ou=Group,dc=example,dc=com </Directory> </VirtualHost> # Upstep to SSL <Virtualhost *:80> ServerAdmin admin@mtak.nl ServerName git.example.com Redirect 301 / https://git.example.com/ </VirtualHost>
Read-only HTTP clones
As a mechanism to deploy software, it might come in handy to have read-only access to the repository for certain servers. I use this mechanism to deploy Puppet code accross the network.
-
Set up Apache HTTPd with the appropriate config:
Alias "/puppet-readonly.git" "/srv/git/puppet.git/" <Directory /srv/git/puppet.git/> AuthName "Puppet git repository" AuthType Basic AuthUserFile /etc/apache2/puppet.git.htpasswd Require valid-user </Directory> -
Create a
.htpasswdfile for authenticationhtpasswd -c /etc/apache2/puppet.git.htpasswd user1 -
When Git clones or pulls a repository over SSH, it discovers references and packs dynamically. This cannot be done over HTTP, so you need to make sure a list up these is updated every time you push changes to the repository. This can be automated by using Git hooks. Uncomment the
exec git update-server-infoline in the repository’shooks/post-update.samplefile and rename it tohooks/post-updateless /srv/git/puppet/hooks/post-update #!/bin/sh # # An example hook script to prepare a packed repository for use over # dumb transports. # # To enable this hook, rename this file to "post-update". exec git update-server-info -
Push a change to the repository to check if the Git hook works.
update-server-infoshould change the following files in the repository:objects/info/packs info/refs -
Access the Git repository through the following url:
git clone https://user1:[email protected]/puppet-readonly.git