Installing Gitlab on Digital Ocean with LDAP and Letsencrypt

In this guide I am installing gitlab on a virtual server hosted at digital ocean. The server only has 512mb of ram which is well below the recommended 2GB . I will be using swap to allow for the installer to finish.If you will be setting up gitlab for more than 50 users then I suggest you get a server with 2gb of ram.

Installation Steps

Update packages , download and run the gitlab install script

apt-get update                                                                                                                                
apt-get dist-upgrade                                                                                                                             
apt-get install curl openssh-server ca-certificates postfix                                                                               
curl -sS https://packages.gitlab.com/install/repositories/gitlab/gitlab-ce/script.deb.sh |  bash                                              
apt-get install gitlab-ce                                                                                                                      

Since gitlab will not run on anything less than 2gb ram we create a swap file

touch swapfile
fallocate -l 2G /swapfile
chmod 600 /swapfile
mkswap /swapfile
swapon /swapfile

Validate the swapfile has been created

swapon -s
free -m

Modify fstab to ensure swap is used after reboot, add the following to the end of the /etc/fstab file

/swapfile   none    swap    sw    0   0

Setup gitlab

gitlab-ctl reconfigure
 

 

Now we start and configure gitlab for the first time

gitlab-ctl reconfigure

Now we need to edit two files with the following info to get the authentication to LDAP working

One is /etc/gitlab/gitlab.rb
........
## For setting up LDAP
## see https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/README.md#setting-up-ldap-sign-in
## Be careful not to break the identation in the ldap_servers block. It is in
## yaml format and the spaces must be retained. Using tabs will not work.

gitlab_rails['ldap_enabled'] = true
gitlab_rails['ldap_servers'] = YAML.load <<-'EOS' # remember to close this block with 'EOS' below
main: # 'main' is the GitLab 'provider ID' of this LDAP server
label: 'LDAP'
host: 'ldap.example.com'
port: 636
uid: 'uid'
method: 'ssl' # "tls" or "ssl" or "plain"
bind_dn: 'cn=gitlab,ou=dsa,dc=example,dc=com'
password: 'mypassword'
active_directory: false
allow_username_or_email_login: true
block_auto_created_users: false
base: 'dc=example,dc=com'
user_filter: ''
attributes:
username: ['uid', 'email' ]
email: ['mail', 'email']
name: 'cn'
first_name: 'givenName'
last_name: 'sn'
EOS

## EE only

and /opt/gitlab/embedded/service/gitlab-rails/config/gitlab.yml

  # 3. Auth settings
  # ==========================

  ## LDAP settings
  # You can inspect a sample of the LDAP users with login access by running:
  #   bundle exec rake gitlab:ldap:check RAILS_ENV=production
  ldap:
    enabled: true
  #  sync_time:
    host: 'ldap.example.com'
    port: 636
    uid: 'uid'
    method:   "ssl" #or "plain"
    bind_dn: 'cn=gitlab,ou=dsa,dc=example,dc=com'
    password: 'add your password'
    active_directory: false
    allow_username_or_email_login:  true
    base: 'dc=example,dc=com'

Thats it all thats left to to is restart gitlab and browse to the url to make sure all is ok

gitlab-ctl restart

Securing the server

Adding Lets-encrypt and enabling firewall

Inside /srv directory i clone the letsencrypt repository

git clone https://github.com/letsencrypt/letsencrypt
We modify /etc/gitlab/gitlab.rb and add the follwoing to modify nginx block
################
# GitLab Nginx #
################
## see: https://gitlab.com/gitlab-org/omnibus-gitlab/tree/master/doc/settings/nginx.md

nginx['redirect_http_to_https'] = true
nginx['ssl_certificate']= "/etc/letsencrypt/live/example.com/fullchain.pem"
nginx['ssl_certificate_key'] = "/etc/letsencrypt/live/example.com/privkey.pem"
nginx['custom_gitlab_server_config']="location ^~ /.well-known {\n alias /var/www/letsencrypt/.well-known;\n}\n"
nginx['custom_gitlab_mattermost_server_config']="location ^~ /.well-known {\n alias /var/www/letsencrypt/.well-known;\n}\n"


I create a conf file for letsencrypt to read info like the domains i wish to generate the certificates for.This file is used for the certificate renewals. The file is in in /srv/letsencrypt/domain.conf and contains the following:

domains=example.com
# increase key size
rsa-key-size = 4096

# the current closed beta (as of 2015-Nov-07) is using this server
server = https://acme-v01.api.letsencrypt.org/directory

# this address will receive renewal reminders, IIRC
email = stelios@milidonis.com

# turn off the ncurses UI, we want this to be run as a cronjob
text = True

# authenticate by placing a file in the webroot (under .well-known/acme-challenge/) and then letting
# LE fetch it
authenticator = webroot
webroot-path = /var/www/letsencrypt

Now we need to reconfigure gitlab to apply the nginx modifications

gitlab-ctl reconfigure

And now we can generate the lets encrypt certificates for the first time

 /srv/letsencrypt/letsencrypt-auto certonly --config /srv/letsencrypt/domain.conf --agree-tos

The lets encrypt certificate s expire every 3 months so i added the following script inside cron.weekly to check if the certificate is about to expire and regenerate it.

/etc/cron.weekly/letsencrypt-update.sh

#!/bin/bash

web_service='nginx'
config_file="/srv/letsencrypt/domain.conf"

le_path='/srv/letsencrypt'
exp_limit=30;

if [ ! -f $config_file ]; then
        echo "[ERROR] config file does not exist: $config_file"
        exit 1;
fi

domain=`grep "^\s*domains" $config_file | sed "s/^\s*domains\s*=\s*//" | sed 's/(\s*)\|,.*$//'`
cert_file="/etc/letsencrypt/live/$domain/fullchain.pem"

if [ ! -f $cert_file ]; then
    echo "[ERROR] certificate file not found for domain $domain."
fi

exp=$(date -d "`openssl x509 -in $cert_file -text -noout|grep "Not After"|cut -c 25-`" +%s)
datenow=$(date -d "now" +%s)
days_exp=$(echo \( $exp - $datenow \) / 86400 |bc)

echo "Checking expiration date for $domain..."

if [ "$days_exp" -gt "$exp_limit" ] ; then
    echo "The certificate is up to date, no need for renewal ($days_exp days left)."
    exit 0;
else
    echo "The certificate for $domain is about to expire soon. Starting webroot renewal script..."
        $le_path/letsencrypt-auto certonly -a webroot --agree-tos --renew-by-default --config $config_file
    echo "Reloading $web_service"
    /usr/sbin/service $web_service reload
    echo "Renewal process finished for domain $domain"
    exit 0;
fi

Enabling ufw

I have enabled ufw for the server and only allowed access for ssh ,http and https
apt-get install ufw
ufw allow 3376
ufw allow 80
ufw allow 443
ufw enable