← Back to Blog

Proxies for CI/CD Pipelines: Configuring GitHub Actions, GitLab CI, and Jenkins for Accessing Private Resources

A complete guide to setting up proxying in CI/CD pipelines: GitHub Actions, GitLab CI, and Jenkins. How to bypass geo-restrictions, access closed APIs, and speed up builds through proxies.

šŸ“…May 16, 2026
```html

Is your pipeline failing with a 403 Forbidden or Connection refused error when trying to access an external API or download a dependency? Most likely, the issue is that the IP address of your CI/CD server is blocked on the resource side. A proxy solves this problem: you route traffic through the desired IP, and the pipeline runs smoothly. This article provides step-by-step instructions for GitHub Actions, GitLab CI, and Jenkins.

Why use a proxy in CI/CD: real scenarios

CI/CD pipelines run on servers with fixed IP addresses — cloud runners from GitHub, GitLab, or on self-hosted Jenkins agents. These IPs are well-known, and many external services either block them or limit the number of requests. Here are specific situations where a proxy is essential:

Access to geo-restricted resources

Many corporate npm registries, Maven repositories, and internal APIs are only accessible from certain countries or IP ranges. If your GitHub Actions runner is located in a region that is blocked at the firewall level of the target service, the pipeline will not be able to download dependencies or send data. A proxy with the required geolocation solves this issue without changing the infrastructure.

Rate limiting and IP blocking

GitHub Actions cloud runners use IPs from Microsoft Azure ranges. Many public APIs are aware of these ranges and impose strict limits — or block them entirely. For example, scraping public data, making requests to third-party APIs during tests, downloading distributions from restricted CDNs — all these tasks frequently fail due to the IPs of cloud runners. Rotating through a proxy allows you to bypass rate limiting.

Integration testing with real websites

If your integration tests access real websites or marketplaces (Wildberries, Ozon, Avito, Amazon), these sites see the same IP from the runner on each run and quickly block it. A rotating IP proxy allows tests to pass consistently without CAPTCHAs and blocks.

Access to internal corporate resources

Corporate networks are often closed off from the outside world. If the pipeline needs to deploy to an internal server or access a closed API, a proxy (or SOCKS5 tunnel) within the corporate network becomes a bridge between the cloud runner and the closed infrastructure.

Testing advertising and marketing integrations

Teams working with Facebook Ads API, TikTok Ads API, or Google Ads API often automate campaign creation through CI/CD. These platforms have strict IP rules: requests from data center IPs may be blocked or require additional verification. Residential proxies in the pipeline make requests appear like regular user traffic.

Which type of proxy to choose for the pipeline

The choice of proxy type depends on the task. For CI/CD pipelines, three options are relevant — each with its own advantages and limitations:

Proxy Type Speed Trust by sites Best for
Datacenter proxies Very high Medium Downloading dependencies, internal repositories, fast APIs without strict checks
Residential proxies Medium High Integration tests with real websites, advertising APIs (Facebook, TikTok), marketplaces
Mobile proxies Medium Maximum Testing mobile APIs, working with platforms with maximum anti-bot protections

Practical rule:

If the task is to download packages or access an internal service, use datacenter proxies — they are fast and cheaper. If the task involves tests on real sites or working with advertising platforms, residential proxies are needed. The SOCKS5 protocol is preferable to HTTP/HTTPS, as it works more transparently with non-standard ports and protocols.

Configuring a proxy in GitHub Actions

GitHub Actions is the most popular CI/CD tool today. Configuring a proxy here is done through environment variables and repository secrets. Let's break it down step by step.

Step 1: Add proxy data to repository secrets

Never write the proxy username and password directly in the YAML workflow file. Use GitHub Secrets:

  1. Open the repository → Settings → Secrets and variables → Actions
  2. Click New repository secret
  3. Create a secret PROXY_URL with a value like http://user:[email protected]:port

Step 2: Use environment variables in the workflow

Most tools (curl, wget, npm, pip, Maven) automatically pick up standard environment variables HTTP_PROXY, HTTPS_PROXY, and NO_PROXY. Example workflow:

name: Build with Proxy

on: [push]

env:
  HTTP_PROXY: ${{ secrets.PROXY_URL }}
  HTTPS_PROXY: ${{ secrets.PROXY_URL }}
  NO_PROXY: localhost,127.0.0.1,internal.company.com

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Install dependencies
        run: npm ci

      - name: Run integration tests
        run: npm test

      - name: Call external API
        run: |
          curl -v https://api.example.com/data

Step 3: SOCKS5 proxy in GitHub Actions

If you are using SOCKS5 (recommended for most tasks), standard environment variables are not enough — a local tunnel is needed. Use the proxychains utility or set up microsocks:

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - name: Setup SOCKS5 proxy tunnel
        run: |
          sudo apt-get install -y proxychains4
          echo "socks5 proxy.host 1080 user password" >> /etc/proxychains4.conf

      - name: Run command through SOCKS5
        run: proxychains4 curl https://restricted-resource.com/api

Configuring a proxy for specific tools

Some tools ignore system variables and require separate configuration:

Tool How to configure the proxy
npm / yarn npm config set proxy http://user:pass@host:port
pip (Python) pip install --proxy http://user:pass@host:port package
Maven Through settings.xml section <proxies>
Gradle systemProp.https.proxyHost=host in gradle.properties
Git git config --global http.proxy http://user:pass@host:port
Docker build --build-arg HTTP_PROXY=http://user:pass@host:port

Configuring a proxy in GitLab CI

GitLab CI provides several levels for setting environment variables: at the project, group, or instance level. This makes proxy management more flexible compared to GitHub Actions.

Step 1: Add variables in GitLab CI/CD Variables

  1. Open the project → Settings → CI/CD → section Variables
  2. Click Add variable
  3. Add the variable PROXY_URL with the type Masked (hides the value in logs)
  4. Value: http://user:[email protected]:port

Step 2: Use variables in .gitlab-ci.yml

variables:
  HTTP_PROXY: $PROXY_URL
  HTTPS_PROXY: $PROXY_URL
  NO_PROXY: "localhost,127.0.0.1,.internal.company.com"

stages:
  - build
  - test
  - deploy

build:
  stage: build
  image: node:20-alpine
  script:
    - npm ci
    - npm run build

integration_tests:
  stage: test
  image: python:3.11
  script:
    - pip install -r requirements.txt
    - pytest tests/integration/

deploy:
  stage: deploy
  script:
    - curl -X POST https://api.external-service.com/deploy
      -H "Authorization: Bearer $DEPLOY_TOKEN"
      -d '{"version": "$CI_COMMIT_SHA"}'

Proxy only for specific jobs

If the proxy is not needed everywhere (for example, only for integration tests but not for building), set the variables at the specific job level rather than globally:

integration_tests:
  stage: test
  variables:
    HTTP_PROXY: $PROXY_URL
    HTTPS_PROXY: $PROXY_URL
  script:
    - pytest tests/integration/

build:
  stage: build
  # Here the proxy is not set — direct connection
  script:
    - npm ci && npm run build

Self-hosted GitLab Runner: configuring a proxy at the runner level

If you are using your own GitLab Runner, you can set the proxy globally in the runner configuration. Open the file /etc/gitlab-runner/config.toml and add to the [runners.env] section:

[[runners]]
  name = "my-runner"
  url = "https://gitlab.com/"
  token = "TOKEN"
  executor = "docker"
  environment = [
    "HTTP_PROXY=http://user:[email protected]:port",
    "HTTPS_PROXY=http://user:[email protected]:port",
    "NO_PROXY=localhost,127.0.0.1"
  ]

This is convenient when all pipelines on this runner need to use the proxy — there is no need to specify it in every .gitlab-ci.yml.

Configuring a proxy in Jenkins

Jenkins is the most flexible of the three tools, but also the most complex to configure. Proxies can be set at several levels: globally for all Jenkins, for a specific Pipeline, or for an individual step.

Method 1: Global proxy settings in Jenkins

  1. Open Manage Jenkins → System
  2. Find the HTTP Proxy Configuration section
  3. Fill in the fields: Server, Port, Username, Password
  4. In the No Proxy Host field, specify internal addresses separated by commas
  5. Click Test URL to check and save

This setting affects the loading of plugins and updates for Jenkins itself, but does not automatically transfer to the runtime environment of pipelines. A separate configuration is needed for pipelines.

Method 2: Proxy in Declarative Pipeline through environment

pipeline {
    agent any

    environment {
        HTTP_PROXY  = credentials('proxy-url-credential')
        HTTPS_PROXY = credentials('proxy-url-credential')
        NO_PROXY    = 'localhost,127.0.0.1,internal.company.com'
    }

    stages {
        stage('Build') {
            steps {
                sh 'npm ci'
                sh 'npm run build'
            }
        }

        stage('Integration Tests') {
            steps {
                sh 'pytest tests/integration/'
            }
        }

        stage('Deploy') {
            steps {
                sh '''
                    curl -X POST https://api.external-service.com/deploy \
                    -H "Authorization: Bearer ${DEPLOY_TOKEN}" \
                    -d "version=${GIT_COMMIT}"
                '''
            }
        }
    }
}

Step 3: Add proxy credentials in Jenkins Credentials

  1. Open Manage Jenkins → Credentials → System → Global credentials
  2. Click Add Credentials
  3. Type: Secret text
  4. ID: proxy-url-credential
  5. Secret: http://user:[email protected]:port

Method 3: Proxy through JVM parameters for Java projects

If your pipeline builds a Java project (Maven, Gradle), system environment variables may not work — the JVM uses its own system properties. Add them to JAVA_OPTS:

environment {
    JAVA_OPTS = '-Dhttps.proxyHost=proxy.host -Dhttps.proxyPort=8080 -Dhttps.proxyUser=user -Dhttps.proxyPassword=password -Dhttp.nonProxyHosts=localhost|127.0.0.1|*.internal.com'
}

Proxying inside Docker containers in the pipeline

Most modern CI/CD pipelines run steps inside Docker containers. Passing the proxy into the container is a separate task that can be solved in several ways.

Passing the proxy through --build-arg when building the image

If the proxy is only needed during the Docker image build (for example, for installing packages inside the Dockerfile), use build arguments:

# In .github/workflows/build.yml or .gitlab-ci.yml
docker build \
  --build-arg HTTP_PROXY=$HTTP_PROXY \
  --build-arg HTTPS_PROXY=$HTTPS_PROXY \
  --build-arg NO_PROXY=$NO_PROXY \
  -t myapp:latest .

# In Dockerfile
ARG HTTP_PROXY
ARG HTTPS_PROXY
ARG NO_PROXY
ENV HTTP_PROXY=$HTTP_PROXY
ENV HTTPS_PROXY=$HTTPS_PROXY
ENV NO_PROXY=$NO_PROXY

RUN apt-get update && apt-get install -y curl
RUN npm ci

āš ļø Important: security when building images

Variables set through ARG and ENV in the Dockerfile are preserved in the image metadata and can be seen via docker inspect. If the proxy requires authentication, ensure that the final image is not published to a public registry — otherwise, the credentials will be publicly accessible.

Global configuration of Docker daemon for proxy

On self-hosted runners, you can configure the proxy for the entire Docker daemon — then all containers will automatically receive the proxy without changes in the Dockerfile:

# /etc/systemd/system/docker.service.d/http-proxy.conf
[Service]
Environment="HTTP_PROXY=http://user:[email protected]:port"
Environment="HTTPS_PROXY=http://user:[email protected]:port"
Environment="NO_PROXY=localhost,127.0.0.1,registry.internal.com"

# Apply changes:
# systemctl daemon-reload
# systemctl restart docker

Security: how to store proxy credentials

Proxy credentials are just as much secrets as API keys or database passwords. Their leakage means that anyone can use your proxy at your expense. Here are the rules for secure storage:

Security checklist

  • āœ… Never write the proxy username/password directly in the pipeline YAML files
  • āœ… Use Masked variables in GitLab and Encrypted secrets in GitHub — they are hidden in logs
  • āœ… In Jenkins, use the Secret text or Username with password type in the Credentials Store
  • āœ… Add NO_PROXY for internal addresses — traffic to your infrastructure should not go through the proxy
  • āœ… Regularly rotate proxy passwords — update only in the secrets store without changing the pipeline code
  • āœ… Use IP authentication for the proxy (whitelist the runner's IP) where supported — this is more reliable than a password
  • āœ… Monitor proxy logs for unusual activity

Proxy URL format: what goes where

Protocol URL format When to use
HTTP http://user:pass@host:port Most tools, npm, pip, curl
HTTPS https://user:pass@host:port Encrypted connection to the proxy server
SOCKS5 socks5://user:pass@host:port Non-standard ports, UDP traffic, maximum compatibility

Common errors and how to fix them

Even after proper configuration, issues may arise. Here are the most common errors and their solutions:

Error: Proxy Authentication Required (407)

Cause: Incorrect username or password, or they are not being passed by the tool.

Solution: Check the URL format — special characters in the password need to be URL-encoded. For example, p@ss#word → p%40ss%23word. Also, ensure that the environment variable is actually being passed to the step — output it using echo $HTTP_PROXY (first few characters) for verification.

Error: SSL Certificate Verification Failed

Cause: The proxy performs SSL inspection (MITM) and replaces the certificate. The client does not trust the proxy's certificate.

Solution: Add the proxy's root certificate to trusted ones. For curl: --cacert /path/to/proxy-ca.crt. For npm: npm config set cafile /path/to/proxy-ca.crt. Alternatively, use a proxy without SSL inspection — this is preferable for CI/CD.

Error: Connection Timeout through proxy

Cause: The proxy server is inaccessible from the runner's IP, or the port is blocked by a firewall.

Solution: Check the proxy's availability with the command nc -zv proxy.host port in the pipeline step. Ensure that the runner's IP is added to the proxy provider's whitelist (if IP authentication is used). For GitHub Actions cloud runners, IP ranges are published at meta.github.com.

Error: Tool ignores HTTP_PROXY variables

Cause: Some tools (especially Java-based) do not read system environment variables.

Solution: Use native proxy configuration for the specific tool (see the table above). For Java, add JVM properties through JAVA_OPTS. For curl, explicitly use the flag -x http://proxy:port.

Error: Internal services also go through the proxy

Cause: The NO_PROXY variable is not set or is set incorrectly.

Solution: Specify all internal domains and IPs in NO_PROXY. Use wildcards for domains: NO_PROXY=localhost,127.0.0.1,10.0.0.0/8,.internal.company.com. Note: some tools support CIDR notation, while others only support exact domains.

Conclusion

Configuring a proxy in a CI/CD pipeline is not a one-time task, but part of a proper automation architecture. We covered three main tools: GitHub Actions (through Secrets and environment variables), GitLab CI (through Variables with masking), and Jenkins (through Credentials Store and Declarative Pipeline). The key principles are the same for all: never store credentials in code, use NO_PROXY for internal addresses, and choose the type of proxy based on the specific task.

Choosing the right type of proxy is critical for pipeline stability. For downloading dependencies and accessing standard APIs, fast datacenter proxies are sufficient. However, if your pipeline conducts integration testing on real sites, works with advertising platforms (Facebook Ads API, TikTok Ads API), or accesses marketplaces — use residential proxies: their IPs are perceived as regular user traffic and are rarely subject to blocks or rate limiting.

The main rule: test the proxy as a separate step at the beginning of the pipeline — this will allow you to quickly diagnose problems and avoid wasting time searching for errors at the end of a long build. Add a step curl -v https://api.ipify.org immediately after setting up the proxy — it will show the IP from which requests are sent and confirm that the proxying works correctly.

```