Phusion white papers Phusion overview

Tutorial: setting up Gitlab on Debian 6

By Hongli Lai on April 21st, 2012

We host many git repositories on our servers using SSH and file system ACLs for access control. However, having been spoiled by Github for so long, this method feels archaic and cumbersome. While Github provides private repositories, sometimes it’s just not an option because there are some things that may never leave the organization. If you still want to have a fancy web interface for your Git repositories, then there are several alternatives:

Gitlab is an excellent option. It’s not as fully featured as Github, but like Gitorious it is open source. We’ve found that it’s not only more user friendly than Gitorious but also easier to install.

This tutorial teaches you how to setup Gitlab on Debian 6, Ruby 1.9.3, Phusion Passenger and Nginx. It assumes that Gitlab and the git repositories are hosted on the same machine. Your Gitlab installation will be protected by SSL. Your users will be able to pull from and push to your repositories using the ssh:// protocol, but they won’t have actual shell access and you don’t need to have separate system accounts for each user to control access. Gitlab (or to be more correct, gitolite, which Gitlab uses) manages access without system accounts.

Step 1: Setup sudo

In this tutorial we’re going to use sudo to switch between user accounts. Sudo is not installed by default on Debian so install it if you don’t already have it:

$ su
# apt-get update
# apt-get install sudo

Now add your own account to /etc/sudoers:

# visudo

Add something like this to the end of the file:

your_username_here   ALL=(ALL) ALL

Step 2: Install the base software

Install basic dependencies:

$ sudo apt-get update
$ sudo apt-get install build-essential git-core wget curl gcc checkinstall libxml2-dev libxslt-dev sqlite3 libsqlite3-dev libcurl4-openssl-dev libreadline-dev libc6-dev libssl-dev libmysql++-dev make build-essential zlib1g-dev libicu-dev redis-server openssh-server python-dev python-pip libyaml-dev

Install Pygments, which Gitlab needs for syntax highlighting:

$ sudo pip install pygments

Gitlab needs the sendmail command in order to send emails (for things like lost password recovery). This command is provided by the exim4, postfix and sendmail packages but you can only have one of them installed. If you don’t already have one of them installed, then we recommend postfix.

First, check whether you already have the sendmail command:

$ ls /usr/sbin/sendmail

If you get a ‘file not found’ then install Postfix:

$ sudo apt-get install postfix

Step 3: Install gitolite

We need gitolite. Gitolite is a tool used by Gitlab for managing access control to git repositories. It works by providing a bunch of config files in which you can register users and their public keys. Gitolite modifies ~/.ssh/authorized_keys appropriately based on the config files’ contents. Gitolite is not supposed to run as root; instead, it runs as a single user.

Install gitolite:

$ sudo apt-get install gitolite

The Debian package will automatically create an account called gitolite. Gitlab controls gitolite by logging into gitolite’s user account through SSH, so we want to create a passwordless SSH keypair for this. This SSH keypair is what we call the gitolite admin key.

$ sudo -u gitolite ssh-keygen
...
Enter file in which to save the key (/var/lib/gitolite/.ssh/id_rsa):    <--- enter nothing here and press enter
...
Enter passphrase (empty for no passphrase):    <--- enter nothing here and press enter
Enter same passphrase again:                   <--  enter nothing here and press enter
...
Your public key has been saved in /var/lib/gitolite/.ssh/id_rsa.pub.
...

Now you need to tell gitolite that you want to use this key as the admin key. First, let’s print the content of the public key and copy it to the clipboard:

$ sudo -u gitolite cat /var/lib/gitolite/.ssh/id_rsa.pub
(now select the output in your terminal and copy it to the clipboard)

Now let’s configure gitolite:

$ sudo dpkg-reconfigure gitolite

When asked for a username, keep it at the default:

When asked for a repository path, keep it at the default:

When asked for the admin key, paste the contents of the key you copied to clipboard:

Finally, we need to set the REPO_MASK option to 0007.

$ sudo -u gitolite vi /var/lib/gitolite/.gitolite.rc

Look for:

$REPO_UMASK = 0077;         # gets you 'rwx------'

Change it to:

$REPO_UMASK = 0007;  # rwxrwx---

Tighten security

We think the default gitolite home directory security is a bit weak: everybody on the system can access the config files and the repository files.

$ ls -ld /var/lib/gitolite
drwxr-xr-x 5 gitolite gitolite 4096 Apr 21 08:40 /var/lib/gitolite

Let’s tighten it up a little bit so that only gitolite can access the files:

$ sudo -u gitolite chmod o-rx /var/lib/gitolite

Step 4: Install Ruby 1.9

Gitlab requires Ruby 1.9 and their developers recommend Ruby 1.9.2, but we don’t recommend 1.9.2 because it has a lot of critical bugs compared to 1.9.3. We’ve been running Gitlab in production on Ruby 1.9.3 for a while now and so far everything works great, so in this tutorial we’ll teach you how to install Ruby 1.9.3. But feel free to install a different version if you disagree with us.

Debian does not provide a recent enough version of Ruby through apt, so we need to install it manually.

$ wget http://ftp.ruby-lang.org/pub/ruby/1.9/ruby-1.9.3-p194.tar.gz
$ tar xzvf ruby-1.9.3-p194.tar.gz
$ cd ruby-1.9.3-p194
$ ./configure
$ make
$ sudo make install

Install Bundler:

$ sudo gem install bundler

Step 5: Install Gitlab

Download the source

$ cd /opt
$ sudo git clone git://github.com/gitlabhq/gitlabhq.git
$ sudo chown -R gitolite:gitolite gitlabhq
$ cd gitlabhq
$ sudo -u gitolite git checkout 9af14e4bda35

(You can also checkout the stable branch for the latest stable version, but this tutorial is written specifically for commit 9af14e4bda35.)

Configure

Setup the database configuration. Make sure you fill in the database details under the production section.

$ sudo -u gitolite cp config/database.yml.example config/database.yml
$ sudo -u gitolite vi config/database.yml

Setup other Gitlab configuration.

$ sudo -u gitolite cp config/gitlab.yml.example config/gitlab.yml
$ sudo -u gitolite vi config/gitlab.yml
  • Set email.from to what should be filled in the ‘From’ header in emails.
  • Set email.to to the domain name on which you want to host Gitlab, without the protocol scheme and without the path.
  • Set email.protocol to https.
  • Set git_host.admin_uri to gitolite@localhost:gitolite-admin.
  • Set git_host.base_path to /var/lib/gitolite/repositories/.
  • Set git_host.host to the system’s SSH domain name.
  • Set git_host.git_user to gitolite.

Now tighten up security:

$ sudo -u gitolite chmod o-rwx config/*.yml

Install gems and setup database

$ sudo -u gitolite -H bundle install --without development test --deployment
$ sudo -u gitolite bundle exec rake db:setup RAILS_ENV=production
$ sudo -u gitolite bundle exec rake db:seed_fu RAILS_ENV=production

This last command will output an initial administrator account’s username and password. Write it down somewhere.

Check status

$ sudo -u gitolite bundle exec rake gitlab:app:status RAILS_ENV=production

You should get all YES:

Starting diagnostic
config/database.yml............exists
config/gitlab.yml............exists
/home/git/repositories/............exists
/home/git/repositories/ is writable?............YES
remote: Counting objects: 603, done.
remote: Compressing objects: 100% (466/466), done.
remote: Total 603 (delta 174), reused 0 (delta 0)
Receiving objects: 100% (603/603), 53.29 KiB, done.
Resolving deltas: 100% (174/174), done.
Can clone gitolite-admin?............YES
UMASK for .gitolite.rc is 0007? ............YES

Run a Resque worker

This worker daemon is for processing background tasks.

$ sudo -u gitolite bundle exec rake environment resque:work QUEUE=* RAILS_ENV=production BACKGROUND=yes

Step 6: Generate an SSL certificate

Generate a self-signed certificate. You may enter arbitrary certificate information but the Common Name must be set to the domain name on which you want to host Gitlab.

$ cd /opt/nginx/conf
$ sudo openssl req -new -x509 -nodes -days 3560 -out gitlab.crt -keyout gitlab.key
$ sudo chmod o-r gitlab.key

Installing the certificate into your browser

This self-signed certificate by itself provides encryption, but not authentication, making it vulnerable to man-in-the-middle attacks. To solve this problem, install this certificate into your browser.

Here’s how you do it on Google Chrome on OS X. First, copy the certificate to your local machine:

$ scp your-server.com:/opt/nginx/conf/gitlab.crt .

Now open Keychain Access. Under the “Keychains” list, select “System”. Then click on the “+” button and add the certificate file.

Step 7: Deploy to Phusion Passenger and Nginx

Install Nginx and Phusion Passenger:

$ sudo gem install passenger --no-rdoc --no-ri
$ sudo passenger-install-nginx-module
(Choose option 1 and install Nginx to /opt/nginx)

Now edit the Nginx config file

$ sudo vi /opt/nginx/conf/nginx.conf

and add this to the http block:

# This is a normal HTTP host which redirects all traffic to the HTTPS host.
server {
    listen 80;
    server_name gitlab.yourdomain.com;
    root /nowhere;
    rewrite ^ https://gitlab.phusion.nl$request_uri permanent;
}

# The actual Gitlab HTTPS host.
server {
    listen 443;
    server_name gitlab.yourdomain.com;
    root /opt/gitlabhq/public;
    ssl on;
    ssl_certificate gitlab.crt;
    ssl_certificate_key gitlab.key;
    add_header Strict-Transport-Security "max-age=315360000";
    location / {
        passenger_enabled on;
    }
    location /assets {
        expires max;
        add_header Cache-Control public;
        passenger_enabled on;
    }
}

Now start Nginx:

$ sudo /opt/nginx/sbin/nginx

And viola, you’re up and running! You can access Gitlab through https://gitlab.yourdomain.com/.

Already have Phusion Passenger installed and already running Ruby 1.8?

Phusion Passenger for Nginx does not yet support multiple Ruby versions (but it will in 3.2). If you already have Ruby apps deployed on your server using Phusion Passenger, and those apps require Ruby 1.8, then you’ll have to run Gitlab on Ruby 1.9 using Phusion Passenger Standalone, and connect it to Nginx through a reverse proxy setup.

$ cd /opt/gitlabhq
$ sudo -u gitolite passenger start -d -e production --max-pool-size 2 -S gitlab.socket

The HTTPS server block should then look like this:

upstream gitlab {
    server unix:/opt/gitlabhq/gitlab.socket;
}

# The actual Gitlab HTTPS host.
server {
    listen 443;
    server_name gitlab.yourdomain.com;
    root /opt/gitlabhq/public;
    ssl on;
    ssl_certificate gitlab.crt;
    ssl_certificate_key gitlab.key;
    add_header Strict-Transport-Security "max-age=315360000";
    proxy_set_header Host $http_host;
    proxy_set_header X-Forwarded-Ssl on;
    location / {
        if (!-f $request_filename) {
            proxy_pass http://gitlab;
            break;
        }
    }
    location /assets {
        expires max;
        add_header Cache-Control public;
        if (!-f $request_filename) {
            proxy_pass http://gitlab;
            break;
        }
    }
}

Donate

Gitlab started a donation campaign a few weeks ago. It is excellent, high-quality open source software so if you like it, consider giving them a donation to support their development.

  • zhando

    Excellent tutorial. Thanks!

  • Pingback: Tutorial: setting up Gitlab on Debian 6 | Debian-News.net - Your one stop for news about Debian

  • https://progval.net/ Valentin Lorentz

    I don’t get the point of using the same user both for gitolite and gitlab. They are two distinct applicatiins. More over, the official guide recommands to create two users.

    I don’t aggree with the system-wide install of Ruby, particularly in a tutorial aimef to Debian users.
    It is clearly cleaner to do a local install for the gitlab user (for example in /home/gitlab/.local) and then update the $PATH. you just have to add the “–configure=/home/gitlab/.local” switch to ./configure.
    That’s what I did and it worked well.

    (PS: I first submitted this comment in French; I die not notice the article was in English. Sorry)

  • https://progval.net/ Valentin Lorentz

    (replace “die” by “did” in the last line)

  • http://www.ebuildy.com Tom

    Nice tuto, I follow everything on my debian then ….

    open browse, enter URL and get this cool passenger message : “Could not find rake-0.9.2.2 in any of the sources (Bundler::GemNotFound)”

    Any idea ?

  • http://www.ebuildy.com Tom

    Ok fixed it, you forgot to mention the ruby path of the passenger config in nginx.conf !

    Now I cannot create a repo ;-( look like gitolie is badly configured …

  • Pingback: Tutorial: setting up Gitlab on Debian 6 | Build Future Repository

  • Pingback: Gitlab on Squeeze « 0ddn1x: tricks with *nix

  • Pingback: Tutorial: setti… « dickytirta

  • Pingback: Instalando Git en Linux + GitLab | Nota para el futuro

  • Gustavo Chaves

    Hey, very nice tutorial. I used it to install GITLAB in my Ubuntu 12.04 making just a few tweaks.

    BTW, I guess you meant to write “voilà” instead of “viola”. They are very different things (http://www.merriam-webster.com/dictionary/voil%C3%A0 and http://en.wikipedia.org/wiki/Viola). :-)

  • Pingback: How to install gitlab on Ubuntu Server 12.04 (precise) the right way — vanutsteen.nl => nerds only

  • Arno Fleming

    Thank you for the information!

    I made an initscript for starting the services automagicaly using the info on http://wiki.debian.org/LSBInitScripts

    user@gitlab:~$ cat /etc/init.d/gitlab 
    #! /bin/sh
    # /etc/init.d/gitlab
    ### BEGIN INIT INFO
    # Provides:          gitlab
    # Required-Start:    $all $redis-server
    # Required-Stop:     $network
    # Should-Stop:       $redis-server
    # Default-Start:     2 3 4 5 
    # Default-Stop:      0 1 6 
    # Short-Description: start webserver and redis / resque for gitlab.
    # Description:       start webserver and redis / resque for gitlab.
    ### END INIT INFO
    #
    
    
    # Carry out specific functions when asked to by the system
    case "$1" in
      start)
        echo "Starting redis/resque worker"
        cd /opt/gitlabhq
        sudo -u gitolite bundle exec rake environment resque:work QUEUE=* RAILS_ENV=production BACKGROUND=yes
        echo "Starting gitlab webserver nginx"
        /opt/nginx/sbin/nginx
        ;;
      stop)
        echo "NOT Stopping redis/resque worker (I don't know how...)"
        echo "Stopping gitolite webserver nginx"
        /opt/nginx/sbin/nginx  -s stop
        ;;
      status)
        sudo -u gitolite bundle exec rake gitlab:app:status RAILS_ENV=production
        ;;
      restart)
        $0 stop
        $0 start
        ;;
      force-reload)
        $0 stop
        $0 start
        ;;
      *)
        echo "Usage: /etc/init.d/gitlab {start|stop|restart|force-reload|status}"
        exit 1
        ;;
    esac
    
    exit 0

    and inserted it with `sudo update-rc.d gitlab defaults`

    Services are up and running without hassle!

  • Daniel van Dorp

    Thanks heaps for this smooth config!
    Made the latest stable run smooth here, with SQLite3 db for more lightweight footprint on my server.

    But I noticed, step 6 and 7 are in the wrong order (at step 6 there is no nginx in /opt)

  • Dman

    When I run the three commands

    $ sudo -u gitolite -H bundle install –without development test –deployment

    $ sudo -u gitolite bundle exec rake db:setup RAILS_ENV=production

    $ sudo -u gitolite bundle exec rake db:seed_fu RAILS_ENV=production

    I get the error “Could not find drapper-0.8.4 in any of the sources”

    I run the bundle install but then again it says drapper not found in any sources.

    Can you help please.

    Thankyou

  • Nigel

    This may be a really daft question!! Why Nginx?? when I already have Apache running as a http server? Thanks.

  • moebius_eye

    Would you kindly tell the user that he doesn’t have to add himself to the sudoers. In fact, it is not at all advised at all on a server.

  • cyryllo

    I have a problem

    Could not find pg-0.14.1 in any of the sources
    Run `bundle install` to install missing gems.

    When you install the missing packages

    sudo bundle install

    An error occurred while installing pg (0.14.1), and Bundler cannot continue.

    Make sure that `gem install pg -v ’0.14.1′` succeeds before bundling.

  • http://www.facebook.com/max.luhrig Max Lührig

    Hi cyrllo,

    had the same trouble.

    sudo -u gitolite -H bundle install –without development test postgres sqlite

    fix it :)

  • bennekrouf

    this gem is yanked

    try to install it manually from : https://rubygems.org/gems/drapper

    then :

    sudo gem install drapper-0.8.2.gem

  • bennekrouf

    sudo gem install rake

  • Daniel Lopez

    Regarding gitorious being difficult to install, try http://bitnami.org/stack/gitorious

  • chinchang

    Nice article. Where does gitlab set the email ID to sent mails about comment notifications and all?

  • Rik

    I’m still having problems with those 3 lines.

    i tried running: “gem install rake -v 0.9.2.2″

    and: “gem install drapper -v 0.8.4″

    but when i re-run the lines they keep on giving the error: “Could not find rake-0.9.2.2 in any of the sources”

    and: “Could not find drapper-0.8.4 in any of the sources”

    i hope anyone will still help me

  • Damien

    Hello, I have the same problem but I don’t know why. Have you fix it?

  • q231950

    try this answer:
    http://stackoverflow.com/questions/16788062/error-running-gem-install-pg-v-0-15-1

    then run again:
    sudo -u gitolite -H bundle install –without development test –deployment

  • Sytse Sijbrandij

    Some updates. Since this article was released GitLab has become much easier to install due to the packages https://about.gitlab.com/downloads/ We’ve also ended the donation compaign since we can fund Gitlab with subscriptions https://about.gitlab.com/subscription/

  • Pingback: CentOS6.3下GitLab+Nginx(SSL)+MySQL+Ruby安装部署 | 我是程序员