AidanMontareDotNet

You are on the old part of aidanmontare.net, which I am no longer maintaining. Newer versions of some of this content can be found on the active part of my site, which you can reach from my homepage.

Custom GitLab Omnibus with Apache

(last updated

Some Notes Before You Begin Reading

This page is still a work in progress. However, you may find it informative to see what I am up to with my research on project management.

Goals of The AidanMontareDotNet Project Management System

  • I want to be able to do development in my free time, and easily share my work with the world through my website. I want others to be able to interact, participate, submit their own code (once I give them permission), and ask questions.
  • This system will be based on Git, because that’s what everybody else uses, and because it seems to be a good choice for managing development branches.
  • The system must include a way of viewing the code through a web interface, viewing diffs, seeing project history, and downloading different versions of the code.
  • The system must also include some basic team management, an issue tracking system, and a way for the average user to get help with their problems.
  • As you can see by the things on my site, I have no experience running open source projects. However, I hope to release many of my projects as open source, and I wanted to learn how to manage larger projects before I actually have to deal with any. So that’s why I am doing things in a somewhat awkward order.
  • The system must make it easy to share small, new, or experimental code, or else I will quickly get lazy and just leave my projects sitting in a directory somewhere on my computer. Creating new projects should be simple and easy enough that I can share even small little things, sort of like GitHub Gist.
  • The system must scale easily to projects that become large. In particular, it should be easy to add other committers, reviewers, etc, and organize these people while maintaining an orderly code base. A good issue tracker and some sort of central communication method should be in place in the event a project becomes large enough to need them.
  • The system should be full-featured enough that the developers can use it as their primary means of communication and collaboration.
  • Each project should have its own independent space, so that all the repositories are not lumped together.
  • A main goal in this site was to learn how to do things independently. Yes, I could easily set up a GitHub account, but then what would I learn? The methods I explain on this page allow most moderately experienced Linux users to create their own, completely independent code management system that requires no outside services and is based on free and open source software. As such, these methods can also be used to create servers for internal projects where a public GitHub repository would not work, or for teams that require intensive customization and scalability for their projects (though doing these things is outside the scope of my advice here, I feel confident that I could do build such a server if a future job required it).
  • The system should be efficient for both the developers, the reviewers and the casual users, preferably as efficient as if I had chose to use the aforementioned hosted solutions.
  • As with building this site, security must be among the top priorities of the system. Unnecessary access to the server should not be required for any users. I should be able to add commiters to a project and still be able to sleep at night.
  • Finally, the system should be lightweight enough that I can run it along with AidanMontareDotNet, and simple enough that one person (me) can manage it.

If your goals are similar to mine, then system may work well for you.

The Components

So what have I come up with? My final system accomplishes all of the goals above (as far as I can tell), and seems pretty manageable and easy to use. It is made up of the following components:

  • The AidanMontareDotNet server: on which everything runs.
  • GitLab: This is the core of my system. GitLab is an open source repository management application that runs on Linux systems. It includes its own Git server, as well as project wikis, team management, issue tracking, access control, and more. It offers many of the features of GitHub, but unlike GitHub, its code is open source and can be installed on your own Linux server. There is also a hosted version that you can use for free.
  • Apache: Apache is the web server I use for this site, so of course I wanted to use it with GitLab. GitLab uses Nginx by default, but it is possible to configure an external web server.
  • Ubuntu Build Virtual Machine: While our initial GitLab installation will be from the default package, we will want to make out own customizations to our GitLab. So we will create an Ubuntu VM in VirtualBox and use this to build our own customized GitLab packages. We can then install these packages on our server like we would install a normal GitLab update. This might seem overkill, but it will make things much easier later on (specifically updating the GitLab installation). This guide will also demonstrate how to use this system to customize the look of the front pages of GitLab to make it fit with an existing website. However, this system would allow for even more extensive changes to the GitLab source.

Assumptions

When writing this guide, I assume the following:

  • You are reasonably comfortable with Linux system administration from the command line. If not, this might be a little overwhelming.
  • You have root privileges on the server you are attempting to install on. Preferably it is your own VPS.
  • You are running a 64 bit OS on your server. As far as I can tell, GitLab only has 64 bit packages.
  • You’re local computer runs a 64 bit Linux distribution or can run one in a virtual machine. This is necessary to create the build machine, which must be the same distribution and architecture as the server you are deploying on.

As I use this system to host all of my public code projects, it should be well tested. Any issues that come about will be listed on this page.

Installing GitLab

security first

As with most major changes I deploy to my server, I like to lock the system down first. I prevent access by limiting the firewall rules to my IP. This will help to prevent someone from messing things up while we try to install stuff and prevent security compromises before we have a chance to secure things.

edit firewall to only allow connections from your ip

On my server, it goes something like this:
sudo vim /etc/iptables.firewall.rules
add "-s [YOUR_IP]" to the allow statements for ports 80 and 443
sudo iptables-restore < /etc/iptables.firewall.rules

If your server is accessible through IPv6, then also make sure to change those firewall rules.

Also, do the same for your firewall rules for port 22 (for Git SSH).

secure sshd

Chances are you already use SSH to manage your server. You likely don’t want anyone else having access your SSH login. However, GitLab will add a git user with a limited shell. This will allow users to clone, pull, push, etc (if they have permission within GitLab) to your projects, but will not allow them to actually log into a SSH console.

For GitLab to work, you want anyone to be able to connect to the git user, but you don’t want to weaken the security of your administration SSH account. we can do this by reconfiguring the ssh daemon:

sudo vim /etc/ssh/sshd_config

Add the following:

# Even if you have SSH on another port for security (good job!), we need to put it on 22 because people who visit your website will want to be able to clone over the normal port
Port 22

# Make sure you have the following set for basic security. A more secure server might have more options:
PermitRootLogin no
PermitUserEnvironment no
PasswordAuthentication no

# Allow the git user from anywhere:
AllowUsers git

# Allow the admin user from only your IP:
# replace admin with the account you use for administration
# replace YOUR_IP with your home IP
Match Address YOUR_IP
AllowUsers git admin
# make sure this is the end of your config file, or you may have problems

Warning: only do this if you have another method of accessing your sever! In the event that your IP changes (mine does so very rarely), you must have another method of getting into your server and changing this rule. Also make a note to yourself somewhere so that if your SSH breaks, you remember to check if your IP has changed.

shutdown apache

sudo service apache2 stop

make a site backup

This is always good practice before you go making big changes to how you do things.
See my WordPress backup script.

configuring your domain

You must now decide under what domain you will be installing GitLab. Mine is at code.aidanmontare.net. I will assume in this guide that you are doing something similar, and that your server already hosts the root of your domain.

If not, there will be some extra work involved to configure a new domain on the server. If you are installing GitLab within a home or office network and will not have a domain, some things will be different as well. However, the general principles listed here should still apply.

configure hosts file

We must configure the hosts file of our server so it knows who it is. Add the following (but with your hostname and domain name):

127.0.0.1       localhost.localdomain localhost
50.116.56.154   AidanMontareDotNetServer.aidanmontare.net AidanMontareDotNetServer code.aidanmontare.net

Some of these may not be necessary, but I have them all in there for redundancy.

now for the install

To start, we basically follow the GitLab installation page.

install dependencies

sudo apt-get install postfix
I will assume you are managing the server over SSH and already have openssh-server, but if not, install that too.

download the latest package

Go to the GitLab installation page and grab the wget command for the latest release. Put the file somewhere convenient.

check the md5 sum

Go to the GitLab download archives page and find the md5 sum of your release. Use the md5sum utility to verify the integrity of the download.

install the package

sudo dpkg -i [PACKAGE_FILE]

Configuring GitLab

We want to use Apache, not the default Nginx, to serve our GitLab installation. That requires some extra configuration.

cleanse the install

For some reason, following the installation instructions as written always seems to give me some difficulties. The fix seems to be to cleanse the install before reconfiguring it, though I don’t know why this is necessary.
sudo gitlab-ctl cleanse

You will get a scary-sounding warning about having 60 seconds to cancel this destructive operation. But of course GitLab has never been configured yet, so you won’t be exactly losing anything. And yes, you really do have to wait the full 60 seconds.

configure GitLab

Now GitLab needs to do its initial configuration. sudo gitlab-ctl reconfigure

edit configuration file

We will disable Nginx and specify what the Apache user is called.
cd /etc/gitlab
sudo vim gitlab.rb

Input the following into that file:

external_url "https://code.YOUR_DOMAIN/"
nginx['enable'] = false
web_server['external_users'] = ['www-data']

YOUR_DOMAIN is something like aidanmontare.net or example.com.

Save the file and run sudo gitlab-ctl reconfigure. This now loads in your configuration changes. GitLab is now installed and ready to go, but you won’t be able to access it yet because we have to configure Apache.

Apache Configuration

give Apache access to the GitLab files

Apache (running as the www-data user on my system) needs access to the GitLab files to be able to serve them. Thus it, must be a member of the gitlab-www user group.
sudo usermod -a -G gitlab-www www-data

Additionally, www-data must be a member of the git group in order for SSH access to your repositories to work:
sudo usermod -a -G git www-data

configure Apache virtual host

On Debian-based systems, each virtual host is a file within /etc/apache2/sites-available. We will create a new virtual host for our GitLab installation.
cd /etc/apache2/sites-available
sudo vim gitlab.conf

Modify this template configuration file to your needs.

On my server, I needed to replace /var/log/httpd/logs/ with ${APACHE_LOG_DIR}. Also, any uses of port 8181 needed to be changed to 8080.

enable Apache modules

Run the following commands to enable the necessary Apache modules for GitLab to work:
sudo a2enmod rewrite
sudo a2enmod ssl
sudo a2enmod proxy
sudo a2enmod proxy_http
sudo a2enmod headers

enable the Apache virtual host

We need to enable the configuration file we created:
sudo a2ensite gitlab

restart Apache

add apache config (see my config file)
add apache modules
restart apache

Testing the Installation

Go to the address of your new GitLab installation in a browser and see what happens!

If you get a deploy page, run sudo gitlab-ctl deploy-page down and refresh the page several times.

If you get some sort of error, try rechecking that you followed all the configuration steps above. Go through everything slowly and flesh out any errors.

Before we go any further, we will do a more thorough check:

  • Open Firefox Developer Tools and select network. Reload a page and make sure none of the resources return errors.
  • Add a new test project.
  • Upload an SSH key in your profile settings.
  • Try cloning the test project.
  • Try pushing to the test project.
  • Try cloning the test project over HTTPS instead of SSH
  • Try pushing over HTTPS
  • Try uploading a project icon and see if it appears correctly

If all of that worked, then we will consider GitLab installed correctly (you can obviously remove the test project, if you wish). If not, recheck your configuration or go to the GitLab support page to see various ways of getting help.

Setting Up the Build VM

For now, I am just using default GitLab until I get the build process working. Stay tuned for more updates.

For now:

After each update:

  1. restore gitlab custom pages
  2. change permissions on backup directory

Building GitLab

Building a Customized GitLab

At the moment, you can achieve the goal of having a custom GitLab omnibus installation without building a custom package. We will accomplish this by editing files over SSH. The files that you might want to check out are:

/opt/gitlab/embedded/service/gitlab-rails/app/helpers/appearances_helper.rb
/opt/gitlab/embedded/service/gitlab-rails/app/views/layouts/explore.html.haml
/opt/gitlab/embedded/service/gitlab-rails/app/views/layouts/_head.html.haml
/opt/gitlab/embedded/service/gitlab-rails/app/views/layouts/devise.html.haml
/opt/gitlab/embedded/service/gitlab-rails/app/views/layouts/notify.html.haml
/opt/gitlab/embedded/service/gitlab-rails/app/views/dashboard/projects/_zero_authorized_projects.html.haml
/opt/gitlab/embedded/service/gitlab-rails/app/views/explore/_head.html.haml

Before you edit these, read this guide to understand how to set your editor to indent correctly, as mistakes in indenting in haml will break GitLab. Also make sure to back up these files before editing them.

When you are done, run sudo gitlab-ctl restart and the changes should take affect.

Beware that this is a temporary solution, as you will have to re-modify the files after every update to GitLab.

Currently I run the following commands to after each update. After each diff where I see that there were no upstream changes, I copy the file from my home directory its location in /opt/gitlab. If there are upstream changes, I modify the file in my home directory to reflect those before copying.

sudo diff appearances_helper.rb /opt/gitlab/embedded/service/gitlab-rails/app/helpers/appearances_helper.rb
sudo diff ~/explore.html.haml /opt/gitlab/embedded/service/gitlab-rails/app/views/layouts/explore.html.haml
sudo diff ~/_head.html.haml /opt/gitlab/embedded/service/gitlab-rails/app/views/layouts/_head.html.haml
sudo diff ~/devise.html.haml /opt/gitlab/embedded/service/gitlab-rails/app/views/layouts/devise.html.haml
sudo diff ~/notify.html.haml /opt/gitlab/embedded/service/gitlab-rails/app/views/layouts/notify.html.haml
sudo diff ~/_zero_authorized_projects.html.haml /opt/gitlab/embedded/service/gitlab-rails/app/views/dashboard/projects/_zero_authorized_projects.html.haml
sudo diff ~/explore_head /opt/gitlab/embedded/service/gitlab-rails/app/views/explore/_head.html.haml
sudo chmod -R g+rx /var/opt/gitlab/backups/ ; sudo gitlab-ctl restart ; sudo gitlab-ctl deploy-page down

Using Your GitLab on The Server

Going Live With Your GitLab

remove security settings

When we first began, we configured our firewall and Apache to only allow our home IP to connect. Now it is time to undo these settings so that the world can connect to our code repositories.

Only proceed if you are ready to début your GitLab installation.

edit firewall rules

Edit your firewall rules with whatever you use to manage them. Remove the IP restrictions from ports 22, 80, and 443 so that any IP can connect. Then reload the firewall rules.

Congratulations!

Your GitLab installation is now complete. Anyone who can access your server will now be able to view and clone your projects.

GitLab Backups

Once we start using our GitLab server, we will start collecting many different projects. While the distributed nature of Git means that all the clones of each repository will have (mostly) all of the repository’s data, we want to have regular backups of our projects on the server in the event something goes wrong.

I use a backup script to make offsite backups of both aidanmontare.net and code.aidanmontare.net. You can download the script I wrote, but be warned you will need to customize it to your server’s setup.

Updating GitLab

Subscribe to the GitLab blog or find another way of keeping up on GitLab news. As with any large web software, there will be security updates that you need to take care of.

Unmodified GitLab

An unmodified GitLab installation can be upgraded quite rapidly. The GitLab update announcement blog posts usually contain information on updating. Additionally, the GitLab documentation has an upgrading guide for Omnibus Packages. Just follow those guidelines and you’ll be good to go.

Customized GitLab

Updating our customized GitLab will take a little more work, but is still relatively quick.

This will be finished once I am doing describing how to create a custom GitLab package.

Emails for GitLab

https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/doc/settings/smtp.md
http://docs.gitlab.com/omnibus/common_installation_problems/README.html#emails-are-not-being-delivered

TODO
http://docs.gitlab.com/ce/incoming_email/README.html

Issues

The issues with using this system, as well as notes on managing open source projects, can be found here.

References

These are the resources I consulted in creating this system. You might find them interesting as well.

GitLab Installation

GitLab
GitLab installation page
GitLab Omnibus Readme
GitLab documentation

GitLab and Apache

GitLab Community Guide Recipe for Apache
https://gitlab.com/gitlab-org/gitlab-recipes/tree/master/web-server/apache
GitLab Nginx Settings

GitLab Omnibus

https://stackoverflow.com/questions/4304438/gem-install-failed-to-build-gem-native-extension-cant-find-header-files

GitLab Customization

building omnibus GitLab
Changing gitlab.yml and application.yml settings

Other References for the Necessary System Configuration

ssh_config man page
sshd_config man page

General Stuff I Consulted

Git Interfaces List
Pro Git Book
Phabricator
how Blender does things
starting an open source project