Skip to content

Use gitlab pages under the same domain as gitlab


Description

Allow the usage of one SSL certificate for both gitlab and gitlab pages

Proposal

You need to reserve a word and prevent the creation of a group with this name (like "admin" is not a valid group name). The main idea is to use a reverse proxy (we use an external nginx) to present the correct Host http header to the gitlab pages server without the user browser knowing it. You still need a DNS wildcard but no Wildcard SSL certificate and the link in Gitlab also works directly (redirects to the correct domain).

Links / references

These issues are partly related

Documentation

Example : gitlab instance runs at https://gitlab.example.org with a nginx reverse proxy in front of it

## gitlab.rb ##
external_url 'https://gitlab.example.org'
gitlab.example.org "http://gitlab.example.org/"
## nginx-vhost.conf ##
server {
    listen 80;
    # Rewrite
    # http://MYGROUP.gitlab.example.org/myproject/index.html
    # to
    # https://gitlab.example.org/pages/MYGROUP/myproject/index.html
    server_name ~^(?<subdomain>.*)\.gitlab.example.org$;
    rewrite ^/(.*)$ https://gitlab.example.org/pages/$subdomain/$1;
}

server {
    listen 80;
    return 301 https://$host$request_uri;
}


server {
    listen 443;

    error_log /var/log/nginx/gitlab.access.log;

    ssl on;
    ssl_certificate /etc/nginx/external/cert.pem;
    ssl_certificate_key /etc/nginx/external/key.pem;
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # don’t use SSLv3 ref: POODLE

    location / {
		# our gitlab runs in another docker container available at gitlab
        proxy_pass http://gitlab:80/;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $http_host;

        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forward-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forward-Proto http;
        proxy_set_header X-Nginx-Proxy true;

        proxy_redirect off;
    }

    location /pages {
        # Redirect http://gitlab.example.org/pages/MYGROUP/MYPROJECT
        # to http://gitlab.example.org/pages/MYGROUP/MYPROJECT/index.html
        # because without the "/" the second rewrite is not working
        rewrite   ^(/pages/[^/]+/[^/]+)$ $1/index.html permanent;
        # Proxy set header with rewrite example:
        # http://gitlab.example.org/pages/MYGROUP/MYPROJECT/index.html
        # to
        # http://gitlab.example.org/MYPROJECT/index.html with header "Host: MYGROUP.gitlab.example.org"
        # see doc here: http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_pass
        rewrite   ^/pages/([^/]+)/(.*)$ /$2 break;
        proxy_set_header Host $1.gitlab.example.org;

        proxy_pass http://gitlab:80/;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $http_host;

        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forward-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forward-Proto http;
        proxy_set_header X-Nginx-Proxy true;

        proxy_redirect off;
    }
}

The two important bits of the Nginx config are

    server_name ~^(?<subdomain>.*)\.gitlab.example.org$;
    rewrite ^/(.*)$ https://gitlab.example.org/pages/$subdomain/$1;

http://group.gitlab.example.org/project is redirected to https://gitlab.example.org/pages/group/project We reserved the name "pages" so no group "pages" can be used in our gitlab instance

and

    location /pages {
        # Redirect http://gitlab.example.org/pages/MYGROUP/MYPROJECT
        # to http://gitlab.example.org/pages/MYGROUP/MYPROJECT/index.html
        # because without the "/" the second rewrite is not working
        rewrite   ^(/pages/[^/]+/[^/]+)$ $1/index.html permanent;
        # Proxy set header with rewrite example:
        # http://gitlab.example.org/pages/MYGROUP/MYPROJECT/index.html
        # to
        # http://gitlab.example.org/MYPROJECT/index.html with header "Host: MYGROUP.gitlab.example.org"
        # see doc here: http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_pass
        rewrite   ^/pages/([^/]+)/(.*)$ /$2 break;
        proxy_set_header Host $1.gitlab.example.org;

I will describe each request with its http header Host to ease comprehension :

https://gitlab.example.org/pages/group/project

Host : gitlab.example.org

is proxyfied as http://gitlab.example.org/project

Host : group.gitlab.example.org

At this point the request hits the nginx bundled with gitlab that forwards it to the gitlab pages server (the correct Host http header is present). I don't know how to integrate into the bundled nginx but I thought it is worth sharing with the community.