doc/administration/geo/secondary_proxy/_index.md
{{< details >}}
{{< /details >}}
{{< history >}}
geo_secondary_proxy_separate_urls. Disabled by default.{{< /history >}}
[!flag] The availability of this feature is controlled by a feature flag. For more information, see the history. The
geo_secondary_proxy_separate_urlsfeature flag is planned to be deprecated and removed in a future release. Support for read-only Geo secondary sites is proposed in issue 366810.
Secondary sites behave as full read-write GitLab instances. They transparently proxy all operations to the primary site, with some notable exceptions.
This behavior enables use-cases including:
<i class="fa-youtube-play" aria-hidden="true"></i> For an overview, see Geo proxying for secondary sites.
<!-- Video published on 2022-01-26 -->For known issues, see proxying-related items in the Geo documentation.
Secondary sites can transparently serve read-write traffic. Therefore, you can use a single external URL so that requests can hit either the primary Geo site or any secondary Geo sites. This delivers a consistent, seamless, and comprehensive experience whichever site the user lands on. Users don't need to juggle multiple URLs or even be aware of the idea of multiple sites.
You can route traffic to Geo sites with:
Follow this example to route traffic to the closest Geo site, whether primary or secondary.
This example creates a gitlab.example.com subdomain that automatically directs
requests:
For this example, you need:
In this example, you use a Route53 Hosted Zone managing your domain for the Route53 setup.
In a Route53 Hosted Zone, traffic policies can be used to set up a variety of routing configurations. To create a traffic policy:
Go to the Route53 dashboard and select Traffic policies.
Select Create traffic policy.
Fill in the Policy Name field with Single Git Host and select Next.
Leave DNS type as A: IP Address in IPv4 format.
Select Connect to, then select Geolocation rule.
For the first Location:
Default.value and fill it in with <your **primary** IP address>.For the second Location:
Europe.value and fill it in with <your **secondary** IP address>.Select Create traffic policy.
Fill in Policy record DNS name with gitlab.
Select Create policy records.
You have successfully set up a single host, like gitlab.example.com, which
distributes traffic to your Geo sites by geolocation.
In this example, you create a GCP Cloud DNS zone managing your domain.
When creating Geo-Based record sets, GCP applies a nearest match for the source region when the source of the traffic doesn't match any policy items exactly. To create a Geo-Based record set:
gitlab.example.com.<**primary** IP address>.<**secondary** IP address>.You have successfully set up a single host, like gitlab.example.com, which
distributes traffic to your Geo sites using a location-aware URL.
After you have set up routing from a single URL to all of your Geo sites, follow the following steps if your sites use different URLs:
On each GitLab site, SSH into each node running Rails (Puma, Sidekiq, Log-Cursor)
and set the external_url to that of the single URL:
sudo -e /etc/gitlab/gitlab.rb
Reconfigure the updated nodes for the change to take effect:
sudo gitlab-ctl reconfigure
To match the new external URL set on the secondary Geo sites, the primary database needs to reflect this change.
In the Geo administration page of the primary site, edit each Geo secondary that
is using the secondary proxying and set the URL field to the single URL.
Make sure the primary site is also using this URL.
To allow the sites to talk to each other, make sure the Internal URL field is unique for each site.
In Kubernetes, you can use the same domain under global.hosts.domain as for the primary site.
You can use different external URLs per site. You can use this to offer a specific site to a specific set of users. Alternatively, you can give users control over which site they use, though they must understand the implications of their choice.
[!note] GitLab does not support multiple external URLs, see issue 21319. An inherent problem is there are many cases where a site needs to produce an absolute URL outside of the context of an HTTP request, such as when sending emails that were not triggered by a request.
If your secondary site uses the same external URL as the primary site, but you want to change it to use a different URL:
On the secondary site, SSH into each node running Rails (Puma, Sidekiq, Log-Cursor)
and set the external_url to the desired URL for the secondary site:
sudo -e /etc/gitlab/gitlab.rb
Reconfigure the updated nodes for the change to take effect:
sudo gitlab-ctl reconfigure
To match the new external URL set on the secondary Geo site, the primary database needs to reflect this change.
In the Geo administration page of the primary site, edit the target secondary site and set the URL field to the desired URL.
To allow the sites to talk to each other, make sure the Internal URL field is unique for each site. If the desired URL is unique to this site, then you can clear the Internal URL field. On save, it defaults to the external URL.
Considering that web traffic is proxied to the primary, the behavior of the secondary sites differs when the primary site is inaccessible:
Most HTTP traffic sent to a secondary Geo site is proxied to the primary Geo site. With this architecture, secondary Geo sites are able to support write requests, and avoid read-after-write problems. Certain read requests are handled locally by secondary sites for improved latency and bandwidth nearby.
The following table details the components tested through the Geo secondary site Workhorse proxy. It does not cover all data types.
In this context, accelerated reads refer to read requests served from the secondary site, provided that the data is up to date for the component on the secondary site. If the data on the secondary site is determined to be out of date, the request is forwarded to the primary site. Read requests for components not listed in the table below are always automatically forwarded to the primary site.
| Feature / component | Accelerated reads? | Notes |
|---|---|---|
| Rails static assets (JavaScript, CSS, fonts, images) | {{< icon name="check-circle" >}} Yes | Assets under /assets/ are served directly from the secondary site's local file system by Workhorse, without being proxied to the primary. This applies to all secondary sites regardless of whether a unified URL or separate URLs are used. After the initial browser request, these assets are also typically cached by the browser. |
| Project, wiki, design repository (using the web UI) | {{< icon name="dotted-circle" >}} No | |
| Project, wiki repository (using Git) | {{< icon name="check-circle" >}} Yes | Git reads are served from the local secondary while pushes get proxied to the primary. If a repository doesn't exist locally on the Geo secondary, for example due to exclusion by selective sync, the request is proxied to the primary site. |
| Project, Personal Snippet (using the web UI) | {{< icon name="dotted-circle" >}} No | |
| Project, Personal Snippet (using Git) | {{< icon name="check-circle" >}} Yes | Git reads are served from the local secondary while pushes get proxied to the primary. If a repository doesn't exist locally on the Geo secondary, for example due to exclusion by selective sync, the request is proxied to the primary site. |
| Group wiki repository (using the web UI) | {{< icon name="dotted-circle" >}} No | |
| Group wiki repository (using Git) | {{< icon name="check-circle" >}} Yes | Git reads are served from the local secondary while pushes get proxied to the primary. If a repository doesn't exist locally on the Geo secondary, for example due to exclusion by selective sync, the request is proxied to the primary site. |
| User uploads | {{< icon name="dotted-circle" >}} No | |
| LFS objects (using the web UI) | {{< icon name="dotted-circle" >}} No | |
| LFS objects (using Git) | {{< icon name="check-circle" >}} Yes | |
| Pages | {{< icon name="dotted-circle" >}} No | Pages can use the same URL (without access control), but must be configured separately and are not proxied. |
| Advanced search (using the web UI) | {{< icon name="dotted-circle" >}} No | |
| Container registry | {{< icon name="dotted-circle" >}} No | The container registry is only recommended for Disaster Recovery scenarios. If the secondary site's container registry is not up to date, the read request is served with old data as the request is not forwarded to the primary site. Accelerating the container registry is planned, upvote or comment in the issue to indicate your interest or ask your GitLab representative to do so on your behalf. |
| Dependency Proxy | {{< icon name="dotted-circle" >}} No | Read requests to a Geo secondary site's Dependency Proxy are always proxied to the primary site. |
| All other data | {{< icon name="dotted-circle" >}} No | Read requests for components not listed in this table are always automatically forwarded to the primary site. |
To request acceleration of a feature, check if an issue already exists in epic 8239 and upvote or comment on it to indicate your interest or ask your GitLab representative to do so on your behalf. If an applicable issue doesn't exist, open one and mention it in the epic.
Secondary site HTTP proxying is enabled by default on a secondary site when it uses a unified URL, meaning, it is configured with the same external_url as the primary site. Disabling proxying in this case tends not to be helpful due to completely different behavior being served at the same URL, depending on routing. When HTTP proxying is disabled on a secondary Geo site, the site operates in read-only mode, with several important limitations you should be aware of.
Disabling the proxying feature flag has the following general effects.
| Feature / component | Succeed | Notes |
|---|---|---|
| Project, wiki, design repository (using the web UI) | {{< icon name="dotted-circle" >}} Maybe | Reads are served from the locally stored data. Writes cause an error. |
| Project, wiki repository (using Git) | {{< icon name="check-circle" >}} Yes | Git reads are served from the locally stored data, while pushes get proxied to the primary. If a repository doesn't exist locally on the Geo secondary, for example due to exclusion by selective sync, it causes a "not found" error. |
| Project, Personal Snippet (using the web UI) | {{< icon name="dotted-circle" >}} Maybe | Reads are served from the locally stored data. Writes cause an error. |
| Project, Personal Snippet (using Git) | {{< icon name="check-circle" >}} Yes | Git reads are served from the locally stored data, while pushes get proxied to the primary. If a repository doesn't exist locally on the Geo secondary, for example due to exclusion by selective sync, it causes a "not found" error. |
| Group wiki repository (using the web UI) | {{< icon name="dotted-circle" >}} Maybe | Reads are served from the locally stored data. Writes cause an error. |
| Group wiki repository (using Git) | {{< icon name="check-circle" >}} Yes | Git reads are served from the locally stored data, while pushes get proxied to the primary. If a repository doesn't exist locally on the Geo secondary, for example due to exclusion by selective sync, it causes a "not found" error. |
| User uploads | {{< icon name="dotted-circle" >}} Maybe | Upload files are served from the locally stored data. Attempting to upload a file on a secondary causes an error. |
| LFS objects (using the web UI) | {{< icon name="dotted-circle" >}} Maybe | Reads are served from the locally stored data. Writes cause an error. |
| LFS objects (using Git) | {{< icon name="check-circle" >}} Yes | LFS objects are served from the locally stored data, while pushes get proxied to the primary. If an LFS object doesn't exist locally on the Geo secondary, for example due to exclusion by selective sync, it causes a "not found" error. |
| Pages | {{< icon name="dotted-circle" >}} Maybe | Pages can use the same URL (without access control), but must be configured separately and are not proxied. |
| Advanced search (using the web UI) | {{< icon name="dotted-circle" >}} No | |
| Container registry | {{< icon name="dotted-circle" >}} No | The container registry is only recommended for Disaster Recovery scenarios. If the secondary site's container registry is not up to date, the read request is served with old data as the request is not forwarded to the primary site. Accelerating the container registry is planned, upvote or comment in the issue to indicate your interest or ask your GitLab representative to do so on your behalf. |
| Dependency Proxy | {{< icon name="dotted-circle" >}} No | |
| All other data | {{< icon name="dotted-circle" >}} Maybe | Reads are served from the locally stored data. Writes cause an error. |
You should use the feature flag over using the GEO_SECONDARY_PROXY environment variable.
HTTP proxying is enabled by default in GitLab 15.1 on a secondary site even without a unified URL.
When proxying is disabled, users who access only the secondary site cannot properly accept terms of service or other legal agreements. This creates the following issues:
As a workaround, you must access the primary site at least once to properly accept terms and conditions. After accepted on the primary, this information is replicated to secondary sites through normal Geo synchronization.
[!note] This limitation affects organizations that require documented acceptance of terms and conditions for compliance or legal purposes. Ensure users have access to the primary site for the initial terms acceptance.
If you need to disable proxying on all secondary sites, it is easiest to disable the feature flag:
{{< tabs >}}
{{< tab title="Linux package (Omnibus)" >}}
SSH into a node which is running Puma or Sidekiq on your primary Geo site and run:
sudo gitlab-rails runner "Feature.disable(:geo_secondary_proxy_separate_urls)"
Restart Puma on all nodes which are running it on your secondary Geo site:
sudo gitlab-ctl restart puma
{{< /tab >}}
{{< tab title="Helm chart (Kubernetes)" >}}
On your primary Geo site, run this command in the Toolbox pod:
kubectl exec -it <toolbox-pod-name> -- gitlab-rails runner "Feature.disable(:geo_secondary_proxy_separate_urls)"
Restart the Webservice pods on your secondary Geo site:
kubectl rollout restart deployment -l app=webservice
{{< /tab >}}
{{< /tabs >}}
To revert the changes so secondary site proxying is enabled again:
{{< tabs >}}
{{< tab title="Linux package (Omnibus)" >}}
SSH into a node which is running Puma or Sidekiq on your primary Geo site and run:
sudo gitlab-rails runner "Feature.enable(:geo_secondary_proxy_separate_urls)"
Restart Puma on all nodes which are running it on your secondary Geo site:
sudo gitlab-ctl restart puma
{{< /tab >}}
{{< tab title="Helm chart (Kubernetes)" >}}
On your primary Geo site, run this command in the Toolbox pod:
kubectl exec -it <toolbox-pod-name> -- gitlab-rails runner "Feature.enable(:geo_secondary_proxy_separate_urls)"
Restart the Webservice pods on your secondary Geo site:
kubectl rollout restart deployment -l app=webservice
{{< /tab >}}
{{< /tabs >}}
If there are multiple secondary sites, you can disable HTTP proxying on each secondary site separately, by following these steps:
{{< tabs >}}
{{< tab title="Linux package (Omnibus)" >}}
SSH into each application node (serving user traffic directly) on your secondary Geo site and add the following environment variable:
sudo -e /etc/gitlab/gitlab.rb
gitlab_workhorse['env'] = {
"GEO_SECONDARY_PROXY" => "0"
}
Reconfigure the updated nodes for the change to take effect:
sudo gitlab-ctl reconfigure
{{< /tab >}}
{{< tab title="Helm chart (Kubernetes)" >}}
You can use --set gitlab.webservice.extraEnv.GEO_SECONDARY_PROXY="0",
or specify the following in your values file:
gitlab:
webservice:
extraEnv:
GEO_SECONDARY_PROXY: "0"
{{< /tab >}}
{{< /tabs >}}
It is not possible to disable forwarding of: