How to Install GitLab with Nginx (SSL) on Ubuntu 16.04

GitLab is a web-based Git repository manager similar to Github. It's an open source git repository management tool powered by Ruby and Rails. It provides a .deb package which contains GitLab Community Edition and all its dependencies including Ruby, PostgreSQL, Redis, Nginx, Unicorn and other gems already compiled.

It offers three different versions. One is a hosted version of GitLab, where you can register for free and you can create as many private and public repositories as you want. it's a big advantage. The second is the ‘GitLab Community Edition’. You can operate the community edition on your own servers and it will cost you no money. It provides a possibility to automatically test and deploy your code, Last but not least, is the ‘GitLab Enterprise Edition'. It is based on top of the community edition and adds some extra features, it is mainly aimed at organizations with more than 100 users.

In this article, I'll explain on how to setup GitLab with Nginx on Ubuntu server. Firstly, you need to make sure that your server meets the basic system requirements.


It is supported in almost all Unix Operating Systems. Please see the minimum System requirements for this installation below:

  • Requires Ruby (MRI) 2.1 minimum.
  • Minimum hardware capabilities with CPU 2 cores and Memory 2GB
  • Three unicorn workers (1+ Number of CPU cores)

Let's walk through the installation steps one by one.

1. Updating APT repository packages

Firstly, we need to make sure that your server is running the latest software packages and they're up to date.

[email protected]:~# apt-get update

Get:1 xenial-security InRelease [94.5 kB] Hit:2 xenial InRelease
Get:3 xenial-updates InRelease [95.7 kB] Get:4 xenial-backports InRelease [92.2 kB] Get:5 xenial-updates/universe amd64 Packages [357 kB] Get:6 xenial-updates/universe i386 Packages [354 kB] Fetched 993 kB in 1s (748 kB/s)
Reading package lists... Done

[email protected]:~# apt-get upgrade

2. Create a Git User

Next step is to create a git user to manage the git repositories in the GitLab.

[email protected]:~# adduser --disabled-login --gecos 'GitLab' git
Adding user `git' ...
Adding new group `git' (1000) ...
Adding new user `git' (1000) with group `git' ...
Creating home directory `/home/git' ...
Copying files from `/etc/skel' ...
[email protected]:~#

3. Installing  GitLab Dependency packages

As discussed before, GitLab requires a minimum of Ruby 2,x version or above. We need to install several dependency packages and development tools to install that software required for the GitLab.

[email protected]:~#apt-get install build-essential cmake zlib1g-dev libyaml-dev libssl-dev libgdbm-dev libreadline-dev libncurses5-dev libffi-dev curl openssh-server redis-server checkinstall libxml2-dev libxslt-dev libcurl4-openssl-dev libicu-dev logrotate

4. Installing Git

We can install Git packages from their repositories by just running this command.

[email protected]:~# apt-get install git

5.  Setup a Mail Server

For receiving the email notifications about our Git projects, we need to configure an email server. I'm currently using PostFix to setup my mail server. You can install Postfix using this single command.

[email protected]~# apt-get install postfix

During the  installation stages, you can select "Internet Site" and enter your FQDN server hostname to complete the installation.

6. How to install / configure Ruby

GitLab is an application purely based on Ruby on Rails. It's  having a version manager which can prevent pushing and pull over SSH. It recommends a Ruby version greater than 2.x.

[email protected]:~# mkdir /tmp/ruby && cd /tmp/ruby
[email protected]:/tmp/ruby# wget
[email protected]:/tmp/ruby# tar xvzf ruby-2.1.2.tar.gz
[email protected]:/tmp/ruby# cd ruby-2.1.2
[email protected]:/tmp/ruby/ruby-2.1.2# ./configure --disable-install-rdoc --prefix=/usr/local
[email protected]:/tmp/ruby/ruby-2.1.2# make
[email protected]:/tmp/ruby/ruby-2.1.2# make install

You can download the supported Ruby version and compile it as above. You can confirm the Ruby version once installed.

[email protected]:/tmp/ruby/ruby-2.1.2# ruby -v
ruby 2.1.2p95 (2014-05-08 revision 45877) [x86_64-linux]

7. Managing Database server for GitLab

Our next step is to create a database for Git lab. I'm using a PostgreSQL database to manage my Git packages. It supports both MySQL and PostgreSQL, but PostgreSQL is recommended over MySQL. You can install it with all required modules as below:

[email protected]:~# apt-get install postgresql postgresql-client libpq-dev

We need to create a database for Gitlab. I've created a new database named "gitlabhq_production" with a user "git" to manage it.

[email protected]:~# su - postgres
[email protected]:~$ postgres createuser --createdb git
[email protected]:~$ createdb --owner=git gitlabhq_production

Finally, you can confirm the DB connectivity with the new user and database name to check the PostgreSQL version using  the commands below:

[email protected]:~# sudo -u git -H psql -d gitlabhq_production -c "SELECT VERSION()"
PostgreSQL 9.5.5 on x86_64-pc-linux-gnu, compiled by gcc (Ubuntu 5.4.0-6ubuntu1~16.04.2) 5.4.0 20160609, 64-bit
(1 row)

If the command results in the PostgreSQL version, then you're good to go.

8) Installing GitLab

Now we're ready to start with the installation. You can download the stable GitLab repository from their official repository site. I've downloaded and installed it to my git home directory.

[email protected]:~# cd /home/git
[email protected]:/home/git# sudo -u git -H git clone -b 6-9-stable gitlab
Cloning into 'gitlab'...
remote: Counting objects: 392871, done.
remote: Compressing objects: 100% (101153/101153), done.
remote: Total 392871 (delta 309481), reused 367895 (delta 286998)
Receiving objects: 100% (392871/392871), 184.55 MiB | 38.25 MiB/s, done.
Resolving deltas: 100% (309481/309481), done.
Checking connectivity... done.

You can select any stable repo branch from there. Here, I've downloaded  6-9-stable branch from the GitLab repository. The important thing to note is that we should never install the Master branch on a production server.

9) Configuring GitLab

Move to your git home directory and copy the sample GitLab configuration file to use it as the main configuration file "gitlab.yml".

[email protected]:/home/git/gitlab# sudo -u git -H cp config/gitlab.yml.example config/gitlab.yml

You need to modify the host to a fully-qualified domain of your server. Furthermore, set the email_from and support_email to the preferred email addresses for GitLab in the configuration file.

[email protected]:/home/git/gitlab#cat /home/git/gitlab/config/gitlab.yml
production: &base
port: 80
https: false
email_from: [email protected]
support_email: [email protected]

Next, we need to correct the ownerships and permissions for the folders to make it work as required. Certain files/folders needed write permissions so that GitLab can write to them as and when needed.

[email protected]:/home/git/gitlab# chown -R git {log,tmp}
[email protected]:/home/git/gitlab# chmod -R u+rwX {log,tmp,tmp/pids,tmp/sockets,public/uploads}

Create the Satellite folders and copy the examples of the unicorn and Rack attack configurations:

[email protected]:/home/git/gitlab# sudo -u git -H mkdir /home/git/gitlab-satellites
[email protected]:/home/git/gitlab# sudo chmod u+rwx,g+rx,o-rwx /home/git/gitlab-satellites

[email protected]:/home/git/gitlab# sudo -u git -H cp config/unicorn.rb.example config/unicorn.rb
[email protected]:/home/git/gitlab# sudo -u git -H cp config/initializers/rack_attack.rb.example config/initializers/rack_attack.rb

10) Database Configuration

The next step is to configure the DB settings, we've to use PostgreSQL for our database. We need to copy the configuration file and change the permissions to make it readable to git:

[email protected]:/home/git/gitlab# sudo -u git cp config/database.yml.postgresql config/database.yml
[email protected]:/home/git/gitlab# sudo -u git -H chmod o-rwx config/database.yml

11) Installing Gems

[email protected]:/home/git/gitlab# sudo gem install bundler
Fetching: bundler-1.13.6.gem (100%)
Successfully installed bundler-1.13.6
Parsing documentation for bundler-1.13.6
Installing ri documentation for bundler-1.13.6
Done installing documentation for bundler after 7 seconds
1 gem installed
[email protected]:/home/git/gitlab# sudo -u git -H bundle install --deployment --without development test mysql aws

12) Installing GitLab shell

You can install GitLab shell which is an SSH access and repository management software for GitLab.

[email protected]:/home/git/gitlab# sudo -u git -H bundle exec rake gitlab:shell:install[v1.9.4] REDIS_URL=redis://localhost:6379 RAILS_ENV=production

git clone '' '/home/git/gitlab-shell/'
Cloning into '/home/git/gitlab-shell'...
remote: Counting objects: 3207, done.
remote: Compressing objects: 100% (1203/1203), done.
remote: Total 3207 (delta 2043), reused 3013 (delta 1885)
Receiving objects: 100% (3207/3207), 481.86 KiB | 0 bytes/s, done.
Resolving deltas: 100% (2043/2043), done.
Checking connectivity... done.

Now we need to edit the gitlab shell configuration file with the exact gitlab URL.

[email protected]:/home/git/gitlab# cat /home/git/gitlab-shell/config.yml
user: git
self_signed_cert: false
repos_path: "/home/git/repositories/"
auth_file: "/home/git/.ssh/authorized_keys"
bin: "/usr/bin/redis-cli"
host: localhost
port: 6379
namespace: resque:gitlab
log_level: INFO
audit_usernames: false

13) Initialize database and activate GitLab

Now, move back to your GitLab home directory and execute this command.

[email protected]:/home/git/gitlab# sudo -u git -H bundle exec rake gitlab:setup RAILS_ENV=production

This will create the necessary database tables and seed the database.
You will lose any previous data stored in the database.
Do you want to continue (yes/no)? Do you want to continue (yes/no)? yes

Adding limits to schema.rb for mysql

== Seed from /home/git/gitlab/db/fixtures/production/001_admin.rb
2016-11-09T06:04:38Z 17990 TID-gtc2554j8 INFO: Sidekiq client with redis options {:url=>"redis://localhost:6379", :namespace=>"resque:gitlab"}

Administrator account created:

[email protected]

You can use this administrator login credentials to access your GitLab interface.

14) Configure the init script

We can copy GitLab init from GitLab installation directory and add GitLab to start at boot time with update-rc.d command:

[email protected]:/home/git/gitlab# cp lib/support/init.d/gitlab /etc/init.d/gitlab
[email protected]:/home/git/gitlab# update-rc.d gitlab defaults 21

Secondly, copy the GitLab logrotate configuration for log management.

[email protected]:/home/git/gitlab# cp lib/support/logrotate/gitlab /etc/logrotate.d/gitlab

And finally,  check the application status and compile assets, configure Git global settings for the git user and start the GitLab service if everything seems good.

[email protected]:/home/git/gitlab# sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production

System information
System: Ubuntu 16.04
Current User: git
Using RVM: no
Ruby Version: 2.1.2p95
Gem Version: 2.2.2
Bundler Version:1.13.6
Rake Version: 10.3.1
Sidekiq Version:2.17.0

GitLab information
Version: 6.9.2
Revision: e46b644
Directory: /home/git/gitlab
DB Adapter: postgresql
SSH Clone URL: [email protected]:some-project.git
Using LDAP: no
Using Omniauth: no

GitLab Shell
Version: 1.9.4
Repositories: /home/git/repositories/
Hooks: /home/git/gitlab-shell/hooks/
Git: /usr/bin/git

Compile status :
[email protected]:/home/git/gitlab# sudo -u git -H bundle exec rake assets:precompile RAILS_ENV=production

Configure Git global settings:
[email protected]:/home/git/gitlab# sudo -u git -H git config --global "GitLab"
[email protected]:/home/git/gitlab# sudo -u git -H git config --global "[email protected]"
[email protected]:/home/git/gitlab# sudo -u git -H git config --global core.autocrlf input

Service start:

[email protected]:/home/git/gitlab# service gitlab start
[email protected]:/home/git/gitlab#
[email protected]:/home/git/gitlab# service gitlab status
● gitlab.service - LSB: GitLab git repository management
Loaded: loaded (/etc/init.d/gitlab; bad; vendor preset: enabled)
and running.
Nov 09 06:13:23 linoxide-gitlab systemd[1]: Started LSB: GitLab git repository management.

15) Install and Configure Nginx

Nginx is the only supported Web server for GitLab. Here we're using Nginx to handle the browser requests. We can install Nginx with the command below:

[email protected]:/home/git/gitlab# apt-get install nginx -y

Now we can copy the Nginx virtual host configuration from the GitLab directory and remove default Nginx default virtual host and restart the Nginx service.

[email protected]:/home/git/gitlab# cp lib/support/nginx/gitlab /etc/nginx/sites-available/gitlab
[email protected]:/home/git/gitlab# rm -f /etc/nginx/sites-enabled/default

Make sure to edit the server name with the GitLab domain. Create a symlink to activate the GitLab virtual host and restart the Nginx service.

[email protected]:/home/git/gitlab# ln -s /etc/nginx/sites-available/gitlab /etc/nginx/sites-enabled/gitlab
[email protected]:/home/git/gitlab# service nginx restart

16) Securing GitLab

In order to secure GitLab, we can install SSL for the GitLab domain and enable SSL for the Nginx Virtual host. I've installed SSL for my GitLab domain using letsencrypt and added to the virtual host.

[email protected]:~/letsencrypt# ./letsencrypt-auto certonly --standalone --email <your email> --agree-tos -d

- Congratulations! Your certificate and chain have been saved at
/etc/letsencrypt/live/ Your cert will
expire on 2017-02-07. To obtain a new or tweaked version of this
certificate in the future, simply run letsencrypt-auto again. To
non-interactively renew *all* of your certificates, run
"letsencrypt-auto renew"
- If you lose your account credentials, you can recover through
e-mails sent to [email protected]
- Your account credentials have been saved in your Certbot
configuration directory at /etc/letsencrypt. You should make a
secure backup of this folder now. This configuration directory will
also contain certificates and private keys obtained by Certbot so
making regular backups of this folder is ideal.
- If you like Certbot, please consider supporting our work by:

Donating to ISRG / Let's Encrypt:
Donating to EFF:

I've added this generated SSL to my GitLab Virtual host. This is how it looks now.

[email protected]:~# cat /etc/nginx/sites-enabled/gitlab
# Maintainer: @randx

# It is a known issue that Git-over-HTTP requires chunked transfer encoding [0] which is not
# supported by Nginx < 1.3.9 [1]. As a result, pushing a large object with Git (i.e. a single large file)
# can lead to a 411 error. In theory you can get around this by tweaking this configuration file and either
# - installing an old version of Nginx with the chunkin module [2] compiled in, or
# - using a newer version of Nginx.
# At the time of writing we do not know if either of these theoretical solutions works. As a workaround
# users can use Git over SSH to push large files.
# [0]
# [1]
# [2]

upstream gitlab {
server unix:/home/git/gitlab/tmp/sockets/gitlab.socket;

server {
listen *:80 default_server; # e.g., listen; In most cases *:80 is a good idea
server_name; # e.g., server_name;
server {
listen 443 ssl;

ssl_certificate /etc/letsencrypt/live/;
ssl_certificate_key /etc/letsencrypt/live/;
server_tokens off; # don't show the version number, a security best practice
root /home/git/gitlab/public;

# Increase this if you want to upload large attachments
# Or if you want to accept large git objects over http
client_max_body_size 20m;

# individual nginx logs for this gitlab vhost
access_log /var/log/nginx/gitlab_access.log;
error_log /var/log/nginx/gitlab_error.log;

location / {
# serve static files from defined root folder;.
# @gitlab is a named location for the upstream fallback, see below
try_files $uri $uri/index.html $uri.html @gitlab;

# if a file, which is not found in the root folder is requested,
# then the proxy pass the request to the upsteam (gitlab unicorn)
location @gitlab {
# If you use https make sure you disable gzip compression
# to be safe against BREACH attack
# gzip off;

proxy_read_timeout 300; # Some requests take more than 30 seconds.
proxy_connect_timeout 300; # Some requests take more than 30 seconds.
proxy_redirect off;

proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

proxy_pass http://gitlab;

# Enable gzip compression as per rails guide:
# WARNING: If you are using relative urls do remove the block below
# See config/application.rb under "Relative url support" for the list of
# other files that need to be changed for relative url support
location ~ ^/(assets)/ {
root /home/git/gitlab/public;
gzip_static on; # to serve pre-gzipped version
expires max;
add_header Cache-Control public;

error_page 502 /502.html;

After making these changes restart the GitLab and Nginx services.

17) Accessing GitLab via Browser

Finally, we are ready to access our GitLab interface via a browser. Before launching it, double check the GitLab application status to confirm everything goes fine.

[email protected]:/home/git# cd gitlab
[email protected]:/home/git/gitlab#sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production

If everything is fine, you can just access your GitLab application by calling the URL >>https://GitLAB-domain-name. In my case, I've installed it on You can access it by using the administrator credentials created during installation, user:

[email protected] or root

Gitlab Login page

You can reset your password to the desired one on login. Let's start building our git projects :)

GitLab Dashboard


GitLab is one of the best solutions to start building your own Git repository server.  It's very easy to install and configure and we can manage it efficiently using its excellent interface. This is used by more 100.000 technology companies. Moreover, it is a powerful software that helps developers to build applications together with other developers. I hope you enjoyed reading this article. Please post your valuable comments and suggestions on this.

Saheetha Shameer 3:00 am

About Saheetha Shameer

Self-motivated and dedicated Linux Administrator having 10 years of working experience on various web-hosting control panels and Unix distributions. I'm a quick learner and have a slight inclination towards following the current and emerging trends in the industry. I'm passionate about testing/reviewing new Linux applications and open source tools.

Author's All Posts
Like to become part of Linoxide Team and contribute tips? Contact us here.


Your email address will not be published. Required fields are marked *

All comments are subject to moderation.