Skip to content

Commit a489b4e

Browse files
ibaumngala
andcommitted
Merge branch 'naman/17584-pages-nginx-namespace-in-path' into 'master'
Add namespace_in_path parameter in GitLab.rb for GitLab Pages See merge request https://gitlab.com/gitlab-org/omnibus-gitlab/-/merge_requests/7250 Merged-by: Ian Baum <[email protected]> Approved-by: Ryan Egesdahl <[email protected]> Approved-by: Ian Baum <[email protected]> Approved-by: Jason Plum <[email protected]> Reviewed-by: Ryan Egesdahl <[email protected]> Co-authored-by: ngala <[email protected]>
2 parents 38f9567 + 11ba7cf commit a489b4e

File tree

12 files changed

+212
-76
lines changed

12 files changed

+212
-76
lines changed

files/gitlab-config-template/gitlab.rb.template

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2007,6 +2007,9 @@ external_url 'GENERATED_EXTERNAL_URL'
20072007
# 'SSL_CERT_DIR' => "#{node['package']['install-dir']}/embedded/ssl/certs/"
20082008
# }
20092009

2010+
# Experimental - Enable namespace in path
2011+
# gitlab_pages['namespace_in_path'] = false
2012+
20102013
################################################################################
20112014
## GitLab Pages NGINX
20122015
################################################################################

files/gitlab-cookbooks/gitlab-pages/attributes/default.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,8 @@
8282
default['gitlab_pages']['redirects_max_path_segments'] = nil
8383
default['gitlab_pages']['redirects_max_rule_count'] = nil
8484
default['gitlab_pages']['register_as_oauth_app'] = true
85+
# Experimental - Enable namespace in path
86+
default['gitlab_pages']['namespace_in_path'] = false
8587

8688
# Temporarily retain support for `node['gitlab-pages'][*]` usage in
8789
# `/etc/gitlab/gitlab.rb`

files/gitlab-cookbooks/gitlab-pages/libraries/gitlab_pages.rb

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ def parse_variables
2929
parse_gitlab_pages_daemon
3030
parse_secrets
3131
parse_automatic_oauth_registration
32+
parse_namespace_in_path
3233
end
3334

3435
def parse_pages_external_url
@@ -134,5 +135,20 @@ def parse_automatic_oauth_registration
134135

135136
LoggingHelper.warning("Writing secrets to `gitlab-secrets.json` file is disabled. Hence, not automatically registering GitLab Pages as an Oauth App. So, GitLab SSO will not be available as a login option.")
136137
end
138+
139+
def parse_namespace_in_path
140+
# If GitLab Pages isn't enabled or namespace_in_path is isn't enabled, do nothing.
141+
return unless Gitlab['gitlab_pages']['enable'] && Gitlab['gitlab_pages']['namespace_in_path']
142+
143+
Gitlab['pages_nginx']['namespace_in_path'] = Gitlab['gitlab_pages']['namespace_in_path']
144+
url_scheme = Gitlab['gitlab_rails']['pages_https'] ? 'https' : 'http'
145+
146+
Gitlab['pages_nginx']['proxy_redirect'] = {
147+
"~^#{url_scheme}://(projects\\.#{Gitlab['pages_nginx']['fqdn_regex']})/(.*)$" => "#{url_scheme}://$1/$2",
148+
"~^#{url_scheme}://(.*)\\.(#{Gitlab['pages_nginx']['fqdn_regex']})/(.*)$" => "#{url_scheme}://$2/$1/$3",
149+
"~^//(.*)\\.(#{Gitlab['pages_nginx']['fqdn_regex']})/(.*)$" => "/$1/$3",
150+
"~^/(.*)$" => "/$namespace/$1",
151+
}
152+
end
137153
end
138154
end

files/gitlab-cookbooks/gitlab-pages/templates/default/gitlab-pages-config.erb

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,3 +191,6 @@ redirects-max-rule-count=<%= @redirects_max_rule_count %>
191191
<%- if @headers -%>
192192
header=<%= @headers.join(';;') %>
193193
<%-end -%>
194+
<%- if @namespace_in_path -%>
195+
namespace-in-path=<%= @namespace_in_path %>
196+
<%-end -%>

files/gitlab-cookbooks/gitlab/recipes/gitlab-rails.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -377,6 +377,7 @@
377377
pages_object_store_enabled: node['gitlab']['gitlab_rails']['pages_object_store_enabled'],
378378
pages_object_store_remote_directory: node['gitlab']['gitlab_rails']['pages_object_store_remote_directory'],
379379
pages_object_store_connection: node['gitlab']['gitlab_rails']['pages_object_store_connection'],
380+
pages_namespace_in_path: node['gitlab_pages']['namespace_in_path'],
380381
mattermost_host: mattermost_host,
381382
mattermost_enabled: node['mattermost']['enable'] || !mattermost_host.nil?,
382383
sidekiq: node['gitlab']['sidekiq'],

files/gitlab-cookbooks/gitlab/templates/default/gitlab.yml.erb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -436,6 +436,7 @@ production: &base
436436
local_store:
437437
enabled: <%= @pages_local_store_enabled %>
438438
path: <%= @pages_local_store_path %>
439+
namespace_in_path: <%= @pages_namespace_in_path %>
439440

440441
## Gravatar
441442
## For Libravatar see: https://docs.gitlab.com/ee/customization/libravatar.html
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# Prevent NGINX from caching pages in response to the pages `Cache-Control`
2+
# header.
3+
#
4+
# Browsers already respect this directive and Pages can handle the request
5+
# volume without help from NGINX.
6+
#
7+
# If this changes in the future, ensure `proxy_cache_key` is set to a value
8+
# like `$scheme$host$request_uri`, as the default value does not take the
9+
# Pages hostname into account, leading to incorrect responses being served.
10+
#
11+
# See https://gitlab.com/gitlab-org/gitlab-pages/issues/73
12+
proxy_cache off;
13+
14+
<% if @proxy_custom_buffer_size -%>
15+
proxy_buffers 8 <%= @proxy_custom_buffer_size %>;
16+
proxy_buffer_size <%= @proxy_custom_buffer_size %>;
17+
<% end -%>
18+
19+
proxy_http_version 1.1;
20+
proxy_pass http://<%= @pages_listen_proxy %>;
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
server_tokens off; ## Don't show the nginx version number, a security best practice
2+
3+
## Disable symlink traversal
4+
disable_symlinks on;
5+
6+
<% if @https %>
7+
## Strong SSL Security
8+
## https://raymii.org/s/tutorials/Strong_SSL_Security_On_nginx.html & https://cipherli.st/
9+
ssl_certificate <%= @ssl_certificate %>;
10+
ssl_certificate_key <%= @ssl_certificate_key %>;
11+
<% if @ssl_client_certificate %>
12+
ssl_client_certificate <%= @ssl_client_certificate%>;
13+
<% end %>
14+
<% if @ssl_verify_client %>
15+
ssl_verify_client <%= @ssl_verify_client%>;
16+
ssl_verify_depth <%= @ssl_verify_depth%>;
17+
<% end %>
18+
19+
# GitLab needs backwards compatible ciphers to retain compatibility with Java IDEs
20+
ssl_ciphers '<%= @ssl_ciphers %>';
21+
ssl_protocols <%= @ssl_protocols %>;
22+
ssl_prefer_server_ciphers <%= @ssl_prefer_server_ciphers %>;
23+
ssl_session_cache <%= @ssl_session_cache %>;
24+
ssl_session_tickets <%= @ssl_session_tickets %>;
25+
ssl_session_timeout <%= @ssl_session_timeout %>;
26+
27+
<% if @ssl_dhparam %>
28+
ssl_dhparam <%= @ssl_dhparam %>;
29+
<% end %>
30+
31+
<% if @ssl_password_file %>
32+
ssl_password_file '<%= @ssl_password_file %>';
33+
<% end %>
34+
<% end %>
35+
36+
## Real IP Module Config
37+
## http://nginx.org/en/docs/http/ngx_http_realip_module.html
38+
<% if @real_ip_header %>
39+
real_ip_header <%= @real_ip_header %>;
40+
<% end %>
41+
<% if @real_ip_recursive %>
42+
real_ip_recursive <%= @real_ip_recursive %>;
43+
<% end %>
44+
<% @real_ip_trusted_addresses.each do |trusted_address| %>
45+
set_real_ip_from <%= trusted_address %>;
46+
<% end %>
47+
48+
## HSTS Config
49+
## https://www.nginx.com/blog/http-strict-transport-security-hsts-and-nginx/
50+
<% unless @hsts_max_age.nil? || @hsts_max_age <= 0 %>
51+
add_header Strict-Transport-Security "max-age=<%= @hsts_max_age -%>
52+
<% if @hsts_include_subdomains %>; includeSubdomains<% end %>";
53+
<% end %>
54+
55+
## Individual nginx logs for this GitLab vhost
56+
access_log <%= @log_directory %>/gitlab_pages_access.log gitlab_access;
57+
error_log <%= @log_directory %>/gitlab_pages_error.log <%= @error_log_level%>;
58+
59+
# Define custom error pages
60+
error_page 403 /403.html;
61+
error_page 404 /404.html;

files/gitlab-cookbooks/gitlab/templates/default/nginx-gitlab-pages-http.conf.erb

Lines changed: 36 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -23,101 +23,63 @@ server {
2323
}
2424
<% end %>
2525

26+
<% if @namespace_in_path %>
27+
## Experimental - Handle requests having namespace in path
28+
## See https://gitlab.com/gitlab-org/gitlab/-/issues/211677
2629
server {
2730
<% @listen_addresses.each do |listen_address| %>
2831
listen <%= listen_address %>:<%= @listen_port %><% if @proxy_protocol %> proxy_protocol<% end %><% if @https %> ssl<% if @http2_enabled %> http2<% end %><% end %>;
2932
<% end %>
30-
server_name ~^(?<group>.*)\.<%= @fqdn_regex %>$;
31-
server_tokens off; ## Don't show the nginx version number, a security best practice
33+
server_name ~^<%= @fqdn_regex %>$;
3234

33-
## Disable symlink traversal
34-
disable_symlinks on;
35+
<%= render "nginx-gitlab-pages-http-common-server.erb" %>
3536

36-
<% if @https %>
37-
## Strong SSL Security
38-
## https://raymii.org/s/tutorials/Strong_SSL_Security_On_nginx.html & https://cipherli.st/
39-
ssl_certificate <%= @ssl_certificate %>;
40-
ssl_certificate_key <%= @ssl_certificate_key %>;
41-
<% if @ssl_client_certificate %>
42-
ssl_client_certificate <%= @ssl_client_certificate%>;
43-
<% end %>
44-
<% if @ssl_verify_client %>
45-
ssl_verify_client <%= @ssl_verify_client%>;
46-
ssl_verify_depth <%= @ssl_verify_depth%>;
47-
<% end %>
37+
# Pass when namespace in path to pages daemon after the rewrite
38+
location ~ ^/(?<namespace>[^/]+)/(?<project>.*)$ {
39+
## Rewrite remove namespace from path
40+
rewrite ^/([^/]+)/(.*)$ /$2 break;
4841

49-
# GitLab needs backwards compatible ciphers to retain compatibility with Java IDEs
50-
ssl_ciphers '<%= @ssl_ciphers %>';
51-
ssl_protocols <%= @ssl_protocols %>;
52-
ssl_prefer_server_ciphers <%= @ssl_prefer_server_ciphers %>;
53-
ssl_session_cache <%= @ssl_session_cache %>;
54-
ssl_session_tickets <%= @ssl_session_tickets %>;
55-
ssl_session_timeout <%= @ssl_session_timeout %>;
42+
<% @proxy_set_headers.each do |header| %>
43+
<% next if header[1].nil? %>
44+
<% if header[0] == "Host" %>
45+
## Put namespace back in host from path
46+
proxy_set_header <%= header[0] %> <%= "$1."+header[1] %>;
47+
<% else %>
48+
proxy_set_header <%= header[0] %> <%= header[1] %>;
49+
<% end %>
50+
<% end %>
51+
proxy_set_header X-Gitlab-Namespace-In-Path $namespace;
5652

57-
<% if @ssl_dhparam %>
58-
ssl_dhparam <%= @ssl_dhparam %>;
59-
<% end %>
53+
<%= render "nginx-gitlab-pages-http-common-server.erb" %>
6054

61-
<% if @ssl_password_file %>
62-
ssl_password_file '<%= @ssl_password_file %>';
63-
<% end %>
55+
## Put namespace in path from host before sending it to the user
56+
<% @proxy_redirect.each do |redirect| %>
57+
proxy_redirect <%= redirect[0] %> <%= redirect[1] %>;
6458
<% end %>
59+
}
6560

66-
## Real IP Module Config
67-
## http://nginx.org/en/docs/http/ngx_http_realip_module.html
68-
<% if @real_ip_header %>
69-
real_ip_header <%= @real_ip_header %>;
70-
<% end %>
71-
<% if @real_ip_recursive %>
72-
real_ip_recursive <%= @real_ip_recursive %>;
73-
<% end %>
74-
<% @real_ip_trusted_addresses.each do |trusted_address| %>
75-
set_real_ip_from <%= trusted_address %>;
76-
<% end %>
61+
<%= @custom_gitlab_server_config %>
62+
}
63+
<% end %>
7764

78-
## HSTS Config
79-
## https://www.nginx.com/blog/http-strict-transport-security-hsts-and-nginx/
80-
<% unless @hsts_max_age.nil? || @hsts_max_age <= 0 %>
81-
add_header Strict-Transport-Security "max-age=<%= @hsts_max_age -%>
82-
<% if @hsts_include_subdomains %>; includeSubdomains<% end %>";
83-
<% end %>
65+
server {
66+
<% @listen_addresses.each do |listen_address| %>
67+
listen <%= listen_address %>:<%= @listen_port %><% if @proxy_protocol %> proxy_protocol<% end %><% if @https %> ssl<% if @http2_enabled %> http2<% end %><% end %>;
68+
<% end %>
69+
server_name ~^(?<group>.*)\.<%= @fqdn_regex %>$;
8470

85-
## Individual nginx logs for this GitLab vhost
86-
access_log <%= @log_directory %>/gitlab_pages_access.log gitlab_access;
87-
error_log <%= @log_directory %>/gitlab_pages_error.log <%= @error_log_level%>;
71+
<%= render "nginx-gitlab-pages-http-common-server.erb" %>
8872

89-
# Pass everything to pages daemon
73+
# Pass everything to pages daemon when namespace in host
9074
location / {
9175
<% @proxy_set_headers.each do |header| %>
9276
<% next if header[1].nil? %>
9377
proxy_set_header <%= header[0] %> <%= header[1] %>;
9478
<% end %>
79+
proxy_hide_header X-Gitlab-Namespace-In-Path;
9580

96-
# Prevent NGINX from caching pages in response to the pages `Cache-Control`
97-
# header.
98-
#
99-
# Browsers already respect this directive and Pages can handle the request
100-
# volume without help from NGINX.
101-
#
102-
# If this changes in the future, ensure `proxy_cache_key` is set to a value
103-
# like `$scheme$host$request_uri`, as the default value does not take the
104-
# Pages hostname into account, leading to incorrect responses being served.
105-
#
106-
# See https://gitlab.com/gitlab-org/gitlab-pages/issues/73
107-
proxy_cache off;
108-
109-
<% if @proxy_custom_buffer_size -%>
110-
proxy_buffers 8 <%= @proxy_custom_buffer_size %>;
111-
proxy_buffer_size <%= @proxy_custom_buffer_size %>;
112-
<% end -%>
113-
114-
proxy_http_version 1.1;
115-
proxy_pass http://<%= @pages_listen_proxy %>;
81+
<%= render "nginx-gitlab-pages-http-common-location.erb" %>
11682
}
11783

118-
# Define custom error pages
119-
error_page 403 /403.html;
120-
error_page 404 /404.html;
121-
12284
<%= @custom_gitlab_server_config %>
12385
}

spec/chef/cookbooks/gitlab-pages/recipes/gitlab-pages_spec.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,7 @@
255255
redirects_max_path_segments: 50,
256256
redirects_max_rule_count: 2000,
257257
enable_disk: true,
258+
namespace_in_path: true,
258259
env: {
259260
GITLAB_CONTINUOUS_PROFILING: "stackdriver?service=gitlab-pages",
260261
},
@@ -329,6 +330,7 @@
329330
redirects-max-path-segments=50
330331
redirects-max-rule-count=2000
331332
header=X-XSS-Protection: 1; mode=block;;X-Content-Type-Options: nosniff;;Test: Header
333+
namespace-in-path=true
332334
EOS
333335

334336
expect(chef_run).to render_file("/var/opt/gitlab/pages/gitlab-pages-config").with_content(expected_content)

0 commit comments

Comments
 (0)