How to get a Static IP for GitLab CI/CD runners - OutboundGateway Blog

How to get a Static IP for GitLab CI/CD runners

July 25, 2026
T
Tom Mikulin
Author

Table of Contents


The problem: GitLab CI/CD runners have no static IP

If you're using the GitLab cloud version or their cloud CI runners, at some point you're probably going to run into a use case of whitelisting an IP from them. You can see those questions popping up on Stack Overflow and even their own GitLab forum.

Most of the time you're going to need a static IP because of GitLab's CI/CD runners, since by default they don't have any stable static outbound IPs. This is confirmed by their own documentation:

"Outgoing connections from CI/CD runners - We don't provide static IP addresses for outgoing connections from CI/CD runners."

But next they mention that even though they don't have static IPs, you can whitelist IPs per their cloud regions:

"Linux GPU-enabled and Linux Arm64 runners are deployed into Google Cloud, in us-central1.

Other GitLab.com instance runners are deployed into Google Cloud in us-east1.

macOS runners are hosted on AWS in the us-east-1 region, with runner managers hosted on Google Cloud.

To configure an IP-based firewall, you must allow both AWS IP address ranges and Google Cloud IP address ranges."

Whitelisting cloud IP ranges is unmanageable

But if you check those IP ranges, you're talking about hundreds if not thousands of IPs. Just imagine if you had to whitelist them all, and again when they change, since you get no guarantee that they will stay static or not change.

AWS (ip-ranges.json):

This file is massive since it includes every IP for virtually all AWS services (EC2, S3, CloudFront, API Gateway, you name it):

  • IPv4 Prefixes: ~1,400 to 1,500 ranges
  • IPv6 Prefixes: ~1,000 to 1,200 ranges
  • Total IPv4 Addresses: roughly 15 to 20 million IP addresses
  • Total IPv6 Addresses: astronomical (billions of times larger than IPv4)

Google (cloud.json):

Although it's substantially smaller than the AWS one, there are still hundreds of IPs involved:

  • IPv4 Prefixes: ~200 to 300 ranges
  • IPv6 Prefixes: ~50 to 100 ranges
  • Total IPv4 Addresses: roughly 3 to 5 million IP addresses
  • Total IPv6 Addresses: also astronomical

Now, everyone can see that this is practically unmanageable to maintain and whitelist, and no client will whitelist hundreds of IPs just so that you can use their service.

A much more sane, practical, and easier approach is to use a static outbound IP proxy like OutboundGateway that gives you two static IPs that will never change, which you can then give to a security team to whitelist, and have peace of mind that they will work.

Configure the proxy in GitLab CI/CD variables

First things first, you need to define the OutboundGateway proxy DNS, port, username, and password in GitLab like so:

Go to Project > Settings > CI/CD > Variables, click on the "Add variable" button, and enter this:

  • Key: OUTBOUNDGATEWAY_URL
  • Value: https://username:password@our-dns-proxy:8443 — you can find the specific values on your OutboundGateway proxy info page (Connection Instructions).

Be careful to choose the "Masked" visibility when creating the variable. It's a security measure which means that the OUTBOUNDGATEWAY_URL value will be hidden in the runner logs.

Route jobs through the proxy

This is an example of a GitLab job (.gitlab-ci.yml) that will route its traffic through the proxy, and it will only be defined on this job, not the whole pipeline, which is what you want in most cases:

variables:
  # define a var

proxy_job:
  stage: build
  image: alpine:latest
  variables:
    HTTP_PROXY: $OUTBOUNDGATEWAY_URL
    HTTPS_PROXY: $OUTBOUNDGATEWAY_URL
    NO_PROXY: "localhost,127.0.0.1,gitlab.com,.gitlab.com"
  script:
    - apk add --no-cache curl
    - curl -I https://outboundgateway.com/ip/  # This request goes through our proxy

If you want to apply the proxy configuration to all the GitLab jobs, you would use this example:

variables:
    HTTP_PROXY: $OUTBOUNDGATEWAY_URL
    HTTPS_PROXY: $OUTBOUNDGATEWAY_URL
    NO_PROXY: "localhost,127.0.0.1,gitlab.com,.gitlab.com"

job_one:
  script:
    - curl -I https://outboundgateway.com/ip/

job_two:
  script:
    - curl -I https://outboundgateway.com/ip/

Since OutboundGateway is an EU startup, EU data residency comes by default when using the service — there's no extra charge to have your traffic stay within EU jurisdiction.

Built with ❤️ for EU businesses who care about privacy and sovereignty.

Frequently Asked Questions (FAQs)

Does GitLab CI/CD provide a static outbound IP?

No. GitLab's own documentation states that outgoing connections from CI/CD runners do not use static IP addresses. The runners run on shared Google Cloud and AWS infrastructure, and the only officially suggested workaround is whitelisting entire cloud IP ranges, which is impractical. Using a static outbound IP proxy like OutboundGateway gives your pipeline a stable, allowlistable IP instead.

How do I route only specific GitLab CI/CD jobs through a proxy?

Define the HTTP_PROXY, HTTPS_PROXY, and NO_PROXY variables inside the variables: block of that individual job rather than at the top of the .gitlab-ci.yml file. Only that job picks up the proxy, while the rest of your pipeline runs normally. This is the recommended approach when you only need certain jobs (for example, one that calls an IP-whitelisted partner API) to egress through the proxy.

Is it safe to put proxy credentials in GitLab CI/CD variables?

Yes, as long as you mark the variable as "Masked" when you create it under Project > Settings > CI/CD > Variables. A masked variable's value is hidden from the runner logs, so your proxy username and password never appear in plain text. Combined with GitLab's protected branches, masked variables keep your outbound proxy credentials secure across the pipeline.

T
Tom Mikulin
Author

OutboundGateway founder