- GitLab, Hub, Sub… same Git, different day
Use cases - my lab, my rules
If I want to post some personal files and host private projects cloud services aren’t my first choices for InfoSec work. Sure, there are many. GitHub, BitBucket… Codeplex… what’s next?
My use cases include committing various archives for Malware Analysis and Forensics. These projects remain private, and I also do not want that some weird AV deletes my work.
Cloud hosters can just delete security-critical content, if they think that it poses risks to their customers and their services. Sometimes the ToS prohibit to commit Malware related content. It doesn’t matter why you do that. It’s not your space anyways.
In order to keep a distance, I host my own GitLab CE server. It’s packed with features, freely available, and useful as a self-hosted service. And it’s in my lab, where I set the rules.
Here’re my tips and tricks.
Works for me - works for you
Here are some service config tricks.
GitLab CE behind an Apache Reverse Proxy
If you have a web-server, or two, as intermediates - as Reverse Proxies - you need to configure them appropriately. The GitLab documentation about this topic scattered, which is why I document my approach here:
- I use an Apache2 ReverseProxy, but an Nginx or Lighttpd will do as well.
- I have a GitLab VM guest, with an internal IP within the
Apache2 ReverseProxy with x-fer headers for GitLab CE
Here is what I put in the
sites-enabled (Debian style config layout) for Apache2:
<VirtualHost *:80> ServerName git.example.com SSLProxyEngine On SSLProxyCheckPeerCN off SSLProxyCheckPeerExpire off ProxyPreserveHost Off ProxyRequests Off ProxyPass / https://git.example.com/ ProxyPassReverse / https://git.example.com/ RequestHeader set X_FORWARDED_PROTO 'https' RequestHeader set X-Forwarded-Ssl on CustomLog /var/log/apache2/code_apache_proxy_https_access.log combined ErrorLog /var/log/apache2/code_apache_proxy_https_error.log </VirtualHost>
The Apache will listen on the external IP, and pass incoming HTTP requests along to the internal IP on port
80. It’s an intermediary as well. I have another service in front for the TLS handling.
In GitLab CE I needed to change the hostname to
git.example.com, to my FQDN to be precise. In the
gitlab.rb this can look like this:
[email protected]:/etc/gitlab# cat gitlab.rb | grep -v "#" | grep external external_url 'https://git.example.com'
In some cases you may need to make sure that the internal host gets the FQDN, either via an
/etc/hosts entry or via split DNS.
This might come in handy as well for your
gitlab_rails['gitlab_hostname'] = 'git.example.com' gitlab_rails['gitlab_ssh_host'] = 'ssh.example.com'
You might want to continue to use SSH from the internal (VPN) network only. Using IPs directly is messy with Git, because of the SSL certificates. If you it that way the GitLab WebUI will display the correct URLs as well.
Result: you can run GitLab behind a Reverse Proxy. It’s supported and easy to do. For now it’s not well documented anywhere, but here I think.
Using self-signed SSL certs for an internal GitLab CE node
Even though Letsencrypt may make this obsolete for 99% of all cases, here is the workflow for that. It’s basically the SSL private key -> CSR (Certificate Signing Request) -> CRT (Certificate) procedure.
First of all we need to disable the letsencrypt support for GibLab:
[email protected]:/etc/gitlab# cat gitlab.rb | grep -v "#" | grep letsencrypt letsencrypt['enable'] = false
Then we need to generate the the self-signed certificate chain.
openssl genrsa -out "git.example.com.key" 2048 openssl req -new -key "git.example.com.key" -out "git.example.com.csr" openssl x509 -req -days 365 -in "git.example.com.csr" -signkey "git.example.com.key" -out "git.example.com.crt"
The FQDN of the cert must fit the service (and hostname). The key needs to be 2048 bits (not 4096). The default is, that you place the certificates into the folder:
[email protected]:/etc/gitlab/ssl# ls | grep example git.example.com.crt git.example.com.csr git.example.com.key
Now keep in mind that there is a naming convention for the Chef /
gitlab-ctl tools. You need to name the files with the
For my internet-facing setup this SSL key does not matter. It does matter for certain GitLab services, like the Docker Registry and the CI / CD pipelines.
Sign GitLab commits
Assuming you have uploaded the respective public key, you need to ensure that the meta-infos of the key match with the GitLab account you are using (same for GitHub):
Git repo config:
git config user.name "marius" git config user.email "[email protected]"
GPG key meta-infos:
➜ tfx1 git:(master) ✗ gpg --list-secret-keys --keyid-format LONG /Users/marius.ciepluch/.gnupg/pubring.kbx ----------------------------------------- sec rsa4096/FEECFC2D782843C9 2019-01-11 [SC] 165F745ED29790C9A023AF58FEECFC2D782843C9 uid [ultimate] Because Security <[email protected]> ssb rsa4096/B2071658FD3FD937 2019-01-11 [E]
Select the respective key for the local repo:
➜ tfx1 git:(master) ✗ git config user.signingkey B2071658FD3FD937
Then sign the commit, either via the command-line
➜ tfx1 git:(master) ✗ git commit -S -m "Initial commit
On MacOS X, if you use Homebrew, you may have to correct the path for
➜ tfx1 git:(master) ✗ which pinentry /usr/local/bin/pinentry ➜ tfx1 git:(master) ✗ more ~/.gnupg/gpg-agent.conf default-cache-ttl 600 max-cache-ttl 7200 pinentry-program /usr/local/bin/pinentry
Now let’s sign the commit on the command-line:
➜ tfx1 git:(master) ✗ export GPG_TTY=$(tty) ➜ tfx1 git:(master) ✗ git commit -S -m "Initial commit" ➜ tfx1 git:(master) ✗ git push origin master
- 17.05.2018 - first version
- 23.12.2018 - updates, corrected English language
- 14.01.2019 - added infos on how to sign commits