Gitlab behind a reverse proxy (Nginx)

Now that we have working sub-URIs projects thanks to Passsenger & Nginx, let’s install a Gitlab instance, on another subdomain:

Gitlab has everything packaged, so when you install it for the forst time, it runs on its own Nginx, with its own unicorn.
It’s cool, but when you want to customize things a bit, it can get scary although it’s simple and the documentation pretty good.

Domain URL

Once the installation done, you have a file existing at: /etc/gitlab/gitlab.rb

Editing this file will let you customize a lot of things, including the URL it will be served on:

external_url ""

IPs, ports,

The trick is that by default Gitlab will listen to requests from any IP, on the default ports (80, 443). 
Wich is not so cool when you have other applications running on the same server !

nginx[‘listen_addresses’] = [‘’, “[::1]”]
nginx[‘listen_port’] = 8081
nginx[‘custom_gitlab_server_config’] = “location ^~/.well-known {\n alias /opt/gitlab/embedded/service/gitlab-rails/public/.well-known;\n}\n”
  1. First we do is re-using our Nginx server as a proxy for Gitlab. Consequence is listening to the whole world becomes useless, so on the first line above, I restrict adresse to localhost (of my server)
  2. Then I change the port the Gitlab’s nginx serves the application, because 80 and 443 are the default for web application only our Nginx proxy should use them (for the outer world).
    Port 8080 is already taken by Gitlab’s unicorn. So here I grab the next one (wich is free)
  3. The thid line is to put in correlation with a previous article where I use Let’s Encrypt as a TLS certificate provider.
    You’ll understand more in the next Nginx section.

Once gitlab.rb configuraiton is done you’ll need to:

sudo gitlab-ctl reconfigure

To let Gitlab reparameterize itself and its internal Nginx with theses new parameters.


Now we need to tell our frontal Nginx proxy to handle external requests for our Gitlab and redirect them to Gitlab’s internal Nginx server.

Open a new file in /etc/nginx/sites-available/gitlab_proxy :

server {
listen *:80 default_server;
listen [::]:80 ipv6only=on default_server;
return 301 https://$server_name$request_uri;
 access_log /var/log/nginx/gitlab_access.log;
error_log /var/log/nginx/gitlab_error.log;
listen ssl default_server;
listen [::]:443 ipv6only=on ssl default_server;
server_tokens off;
 location ~ /.well-known {
allow all;
location /{
proxy_pass http://localhost:8081;
proxy_redirect off;
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_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Protocol $scheme;
proxy_set_header X-Url-Scheme $scheme;

The first server block is the usual HTTP redirecting to HTTPS.
I customized the logs to keep gitlab’s log from my other domains logs, but you do not have to do that. That’s puerely confirm for me. Not mandated.

The second server block defines TLS configration, the usual port, same domain etc.
Difference comes from teh 2 locations:

  1. .well-known is specific to let’s Encrypt and needed for certificates renewall
  2. The second does the redirection trick to the internal Nginx.
    Note how we give the specific port defined earlier so it find the proper application as several can be served on localhost, but on different ports.

Do not forget to create the symlink to /etc/nginx/sites-enabled and restart nginx ;)

If I forgot anything, or got wrong or more complicated than needed, please tell me ! I’m always eager to learn a better way :)