Free tools Windows power users keep installed
One-click scans. No signup required.
The reliable way to put a self-hosted GitLab server behind NGINX is to choose one NGINX owner for the public listener, keep GitLab’s public URL accurate, and pass the original host and HTTPS scheme in forwarding headers. Linux package installations include bundled NGINX by default, but an existing NGINX can take over ports 80 and 443 when you disable the bundled service and grant the external web-server user access.
Need a server to try this on? Antihost offers Linux VPS plans with NVMe storage, full root access and a 14-day free trial.
Choose who owns ports 80 and 443
There are two supported designs. In the bundled design, the Linux package manages NGINX and generates its configuration from /etc/gitlab/gitlab.rb. In the external design, your existing NGINX owns the public listeners and reverse-proxies requests to GitLab. Do not let both instances compete for the same address and port.
As an Amazon Associate I earn from qualifying purchases.
Crashes, No Sound, or Screen Glitches?
Random freezes, missing sound and display glitches usually trace back to one bad driver. Find and replace yours safely.Free scan · under a minuteWindows Errors? Fix Them Before They Spread
Repair common Windows errors and clear accumulated junk for a smoother, more stable PC - no reinstall needed.Free scan · no reinstall| Decision point | Bundled NGINX | External NGINX |
|---|---|---|
| Public listener | GitLab’s package-managed NGINX binds the configured addresses and ports. | Your existing NGINX binds ports 80 and/or 443. |
| Configuration owner | GitLab generates the server configuration from gitlab.rb. |
You maintain the public reverse-proxy server block; GitLab still manages its application services. |
| TLS termination | Usually terminates in the GitLab-managed NGINX. | Can terminate at the external NGINX or at another upstream load balancer. |
| Proxy headers | Generated defaults are based on external_url and GitLab settings. |
You must preserve the public host, port, client address, and scheme explicitly. |
| Auxiliary services | Registry, Pages, and KAS use their own NGINX setting hashes. | The external proxy needs routing for each published service, while each GitLab service still has separate settings. |
Use the bundled option when you want the package to generate and maintain the GitLab-facing NGINX configuration. Use an external instance when NGINX is already a shared ingress, when certificates are centralized, or when one proxy must serve several applications. The rest of this guide keeps the two paths separate so that a setting intended for one topology is not accidentally applied to the other.
Set the public URL before changing proxy behavior
GitLab builds links, redirects, cookie scope, and scheme checks from its public URL. Set external_url to the address users actually enter, including https:// when users reach GitLab over HTTPS. Do not substitute an internal hostname or backend port for the public address.
#1 Best Overall
- B5 Recipe Book: This hardcover blank recipe book measures 10''×7.3'', containing 150 blank pages, comes with 1 sheet of DIY category stickers, perfect for writing down your own recipes and organizing them in one place.
- Practical Layout - 5 pages of conversion charts show you everything you'll ever need to know in the kitchen. The table of contents will help organize your personal favorite recipes. A back pocket is designed for loose items.
- Easy to Use - This blank cookbook is made of high-quality paper with a beautiful hardcover for long-term use. The sturdy gold double-wire spiral binding makes writing easier and page turning smoother.
- Make Your Own Recipes - This blank cookbook has up to 150 blank pages for you to write in your own recipes, with plenty of space to record ingredients and instructions. You can write down all the special tips for your family members.
- Thoughtful Gift - A personalized recipe book makes a thoughtful gift for your children or newlyweds, and a great gift for housewarming, weddings, bridal showers, anniversaries, or any other occasion.
external_url 'https://gitlab.example.com'
The hostname in this value must match the host that the browser sends to NGINX. If a proxy terminates TLS, GitLab can still use an HTTPS external_url; the connection from that proxy to the GitLab-side listener may be plain HTTP. That distinction is what lets GitLab generate HTTPS links without requiring encryption on every internal hop.
Configure the bundled NGINX
Keep the package-managed listener
Bundled NGINX is the default for GitLab Linux package installations. Put supported values in /etc/gitlab/gitlab.rb, then regenerate the service configuration:
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
sudo gitlab-ctl reconfigure
GitLab owns the generated server block in this topology. Avoid editing generated files directly: a later reconfigure can replace those edits. For a normal single-host installation, the essential inputs are the correct external_url, the intended certificate and key settings if GitLab is terminating TLS, and any service-specific NGINX options documented for your GitLab version.
Put custom directives in the supported extension point
If you need a custom server block or a narrowly scoped NGINX directive, use GitLab’s custom configuration mechanism rather than replacing the generated root configuration. The package supports an include directory configured with nginx['custom_nginx_config']. For example:
nginx['custom_nginx_config'] = '/etc/gitlab/nginx/custom'
Create the directory structure and place only the additional files there:
sudo mkdir -p /etc/gitlab/nginx/custom/sites-available
sudo mkdir -p /etc/gitlab/nginx/custom/sites-enabled
sudo ln -s /etc/gitlab/nginx/custom/sites-available/example.conf
/etc/gitlab/nginx/custom/sites-enabled/example.conf
After changing an included file, reload the GitLab-managed NGINX without rebuilding every service:
sudo gitlab-ctl hup nginx
A restart is another option when a reload is not sufficient. Do not redefine GitLab’s generated root or /assets locations. GitLab notes that added locations may require proxy_cache off, HTTP/1.1, and an upstream of http://gitlab-workhorse so that application behavior is preserved.
Move the public listener to an existing NGINX
Disable the bundled listener and identify the web-server user
For an external NGINX, edit /etc/gitlab/gitlab.rb and disable the package-managed NGINX. Also tell GitLab which operating-system user your external NGINX uses. Debian and Ubuntu commonly use www-data; RHEL and CentOS commonly use nginx.
nginx['enable'] = false
web_server['external_users'] = ['www-data']
Replace www-data with the account that actually runs your external NGINX. The account needs the access GitLab documents for the sockets, files, and application endpoints used by the reverse proxy. Apply the change:
sudo gitlab-ctl reconfigure
Only after this reconfigure should the external NGINX take over the public address. If another service already occupies port 80 or 443, resolve that listener conflict before testing GitLab.
Create an external reverse-proxy server block
The internal destination is deployment-specific, so do not copy a guessed address or port. Point proxy_pass at the GitLab endpoint that your installation exposes to the external NGINX. The important part is that every GitLab path reaches the same upstream and that the public request metadata is retained.
server {
listen 443 ssl;
server_name gitlab.example.com;
# Configure ssl_certificate and ssl_certificate_key for this host.
location / {
proxy_pass http://<gitlab-internal-host>:<gitlab-internal-port>;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Port $server_port;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Ssl on;
}
}
Use the public hostname in server_name and in the Host header. X-Forwarded-Proto must be https for an HTTPS client, and X-Forwarded-Port must describe the public port. GitLab specifically calls out X-Forwarded-Ssl, X-Forwarded-For, and X-Forwarded-Port; generated configurations also use X-Forwarded-Proto when external_url is HTTPS.
If the external NGINX also accepts plain HTTP, use a separate port-80 server that redirects to the public HTTPS URL. The HTTPS proxy request must still send the forwarding headers shown above. A redirect loop usually means the proxy is telling GitLab that the internal HTTP hop is the public scheme, rather than reporting the browser’s original HTTPS request.
Terminate TLS at a proxy without redirect loops
When a load balancer or external NGINX terminates TLS before GitLab’s generated listener, keep the public URL set to HTTPS but configure the GitLab-side NGINX listener for plain HTTP:
Quick wins for a faster PC:
Clear out junk files and repair common Windows errorsFree Scan →Scan for outdated or missing drivers - takes under a minuteDriver Scan →gitlab_rails['nginx']['listen_port'] = 80
gitlab_rails['nginx']['listen_https'] = false
Then apply the settings:
sudo gitlab-ctl reconfigure
This arrangement is appropriate when GitLab’s own generated NGINX still handles the internal request. If you have disabled the bundled listener and proxy directly to another GitLab endpoint, use the equivalent topology-specific backend settings and still preserve the public HTTPS headers at the external proxy. The key rule is consistent scheme reporting: the browser sees HTTPS, external_url remains HTTPS, and the proxy tells GitLab that the original request was HTTPS even if the backend connection is HTTP.
Rank #2
- Create a Culinary Legacy: The Pipilo Press Blank Family Cookbook Recipe Binder offers a timeless platform for chronicling beloved recipes. With its hardcover and spiral binding, this recipe book to write in your own recipes ensures durability and ease of use for generations
- Thoughtful Gifting Choice: This book for writing recipes is an ideal present for various occasions, adding a personal touch to celebrations. Its elegant design makes it perfect for moms cookbook DIY projects or anyone passionate about preserving family traditions
- Durable Design Features: Constructed with a 300gsm cardstock cover and matte lamination, this cookbook you can write in ensures longevity. Its spiral-bound format provides convenient access to pages, making it a practical tool for everyday use
- Organized Recipe Storage: The included memo pocket offers a space to store handwritten notes or recipe cards, enhancing its functionality. This feature transforms the recipe book for moms into a sentimental family memento
- Ample Writing Space: Measuring 6.5 x 8.2 inches, this blank spiral family recipe cookbook offers plenty of room for detailed notes. It is perfect for jotting down ingredients, preparation methods, and serving suggestions for a complete culinary record
Do not “fix” a loop by changing external_url to an internal HTTP URL. That can stop one redirect while producing insecure links, incorrect clone URLs, and inconsistent callback behavior.
Apply changes in the right order
- Record the topology. Write down which process owns ports 80 and 443, where TLS ends, the public hostname, and the exact internal GitLab endpoint.
- Edit
gitlab.rb. Setexternal_url; disable bundled NGINX and setweb_server['external_users']only when using an external instance. Add GitLab-side listener settings when a proxy fronts a GitLab-managed listener. - Reconfigure GitLab. Run
sudo gitlab-ctl reconfigureafter changinggitlab.rb. - Install or update the external server block. Preserve
Host,X-Forwarded-For,X-Forwarded-Port,X-Forwarded-Proto, and, for TLS termination,X-Forwarded-Ssl. - Reload the correct NGINX. For GitLab-managed NGINX, use
sudo gitlab-ctl hup nginxafter custom include changes. Reload your standalone NGINX using its normal service procedure after changing its server block. - Test from the public hostname. Check the sign-in page, a project page, repository clone URLs, file uploads, and any published Registry, Pages, or KAS endpoint. Test both HTTP redirection and HTTPS if both are exposed.
Certificate replacement is a separate operational case. GitLab notes that changing certificate files without changing gitlab.rb may not be acted on by gitlab-ctl reconfigure alone. Follow the certificate deployment and reload procedure for the component that terminates TLS, then reload that NGINX.
Make client IP handling trustworthy
Forwarded client addresses are security-sensitive. If NGINX is itself behind another proxy, list the actual address ranges of that trusted proxy in GitLab’s real-IP settings. Do not trust every address or blindly trust values supplied by internet clients.
gitlab_rails['nginx']['real_ip_trusted_addresses'] = ['10.20.0.0/16', '192.0.2.15/32']
gitlab_rails['nginx']['real_ip_header'] = 'X-Forwarded-For'
gitlab_rails['nginx']['real_ip_recursive'] = 'on'
The networks above are examples of syntax only; replace them with the addresses used by your own upstream proxy. These settings affect the client IP recorded in logs and the addresses GitLab treats as trusted. Set them only after mapping every hop in the chain. Reconfigure GitLab after changing the file.
Use the PROXY protocol only when every client supports it
HAProxy and some load balancers can send the PROXY protocol, which carries connection metadata outside ordinary HTTP headers. If your upstream is configured that way, enable the matching GitLab setting and configure the trusted upstream addresses:
gitlab_rails['nginx']['proxy_protocol'] = true
A listener configured for PROXY-protocol traffic expects that protocol on incoming connections. Health checks, monitoring probes, direct administrative requests, and any other clients must use the same protocol or they can fail before HTTP processing begins. Do not enable this option merely because an upstream proxy exists; enable it only when the listener’s clients consistently send PROXY protocol.
Configure Registry, Pages, and KAS separately
GitLab’s Rails application and its auxiliary services do not share one universal NGINX hash. Modern package configuration uses separate sections such as:
gitlab_rails['nginx']for the Rails application.registry['nginx']for the Container Registry.gitlab_pages['nginx']for GitLab Pages.gitlab_kas['nginx']for the Kubernetes Agent Server.
A setting placed in one service’s hash does not automatically propagate to the others. If both GitLab and the Registry must redirect HTTP to HTTPS, configure the redirect behavior for both services. The same principle applies to listener ports, trusted proxy addresses, real-IP processing, and proxy protocol: verify each published service’s own configuration instead of assuming the Rails setting covers it.
Diagnose common failures by symptom
“The change you wanted was rejected” or a 422 CSRF error
Check the request metadata before changing Rails or disabling CSRF protection. Confirm that the external proxy sends the public Host, the original X-Forwarded-Proto, the public X-Forwarded-Port, and the TLS indicator expected by your topology. A proxy that sends http for an HTTPS browser request can make GitLab reject the session or redirect to the wrong scheme.
Redirects alternate between HTTP and HTTPS
Compare three values: external_url, the scheme visible to the browser, and X-Forwarded-Proto received by GitLab. For TLS termination at the proxy, keep external_url as HTTPS, set the GitLab-side listener to HTTP where applicable, and send X-Forwarded-Proto https (plus X-Forwarded-Ssl on) on the proxied request. Do not expose two competing GitLab NGINX listeners with different scheme assumptions.
The Tool Desk
Outbyte PC Repair FREEClear out junk files and repair common Windows errorsFree Scan →Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →Logs show the proxy’s address instead of the user’s
Verify the complete proxy chain and set real_ip_trusted_addresses to the actual upstream ranges. Pair it with real_ip_header = 'X-Forwarded-For' and enable recursive processing only when the chain requires it. If an untrusted hop can inject the header, the recorded client address is not reliable.
Connections fail immediately after enabling PROXY protocol
The listener is now expecting a PROXY-protocol preamble. Ensure that the load balancer, health checks, and direct clients all use the protocol. If some clients cannot, disable the option on that listener or isolate those clients behind a listener with matching expectations.
A custom location breaks assets or streaming behavior
Do not replace GitLab’s generated root or /assets locations. Review custom locations for the settings GitLab identifies as important: proxy_cache off, proxy_http_version 1.1, and proxy_pass http://gitlab-workhorse; where appropriate. For supported header overrides, GitLab recommends the proxy_set_headers setting in gitlab.rb rather than incompatible proxy_set_header directives in a custom server configuration.
Changing a certificate appears to have no effect
Reconfigure only regenerates settings from gitlab.rb; it does not necessarily redeploy a certificate file that changed in place. Confirm which NGINX terminates TLS, deploy the certificate according to that component’s SSL procedure, and perform the required reload or restart.
Production checklist
- The public hostname in
external_urlmatches the browser-facing hostname. - Exactly one intended NGINX owns each public listener.
- The external NGINX account is declared with
web_server['external_users']when bundled NGINX is disabled. - Every proxied request preserves
Host,X-Forwarded-For,X-Forwarded-Port, andX-Forwarded-Proto; TLS termination also preservesX-Forwarded-Ssl. - GitLab-side HTTP listener settings are used when TLS ends before a GitLab-managed listener.
- Trusted proxy ranges represent real infrastructure, not the whole internet.
- PROXY protocol is enabled only when all clients and health checks send it.
- Registry, Pages, and KAS settings are reviewed independently.
- Changes in
gitlab.rbare followed bysudo gitlab-ctl reconfigure; custom GitLab-managed NGINX changes are followed bysudo gitlab-ctl hup nginx. - Certificate updates include the appropriate deployment and NGINX reload procedure.
With those boundaries in place, NGINX can terminate HTTPS, preserve the request identity GitLab needs, and route the Rails application and auxiliary services without redirect or CSRF surprises.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.




