GitHub Actions and Static IPs: Deploying to Firewalled Servers from CI/CD

QuotaGuard Engineering
April 7, 2026
5 min read
Pattern

GitHub Actions hosted runners share IP addresses with every other GitHub Actions user. GitHub publishes the ranges, but they cover thousands of addresses across all customers. If your deployment pipeline needs to reach a server that requires IP whitelisting, this is a problem.

Common scenarios: deploying to a staging server behind a corporate firewall, pushing artifacts to an IP-restricted registry, running database migrations against a production database with security groups, or calling an API that authenticates by source IP.

Why GitHub's Published IP Ranges Don't Help

GitHub publishes the IP ranges used by hosted runners. You can fetch them from https://api.github.com/meta under the actions key. But these ranges are broad. They cover all hosted runners across all GitHub customers.

Whitelisting the full range means opening your firewall to traffic from every GitHub Actions workflow running anywhere. That defeats the purpose of IP whitelisting. Most security teams won't approve it, and for good reason.

Self-Hosted Runners: The Heavy Fix

One option is running your own GitHub Actions runners on infrastructure you control. You set up a VM with a static IP, install the runner agent, and your workflows execute there. You know the IP because it's your machine.

This works, but now you're maintaining runner infrastructure. Patching, scaling, monitoring uptime, handling runner updates. For teams that just need one step in a pipeline to come from a known IP, it's a lot of overhead.

The Proxy Approach

A simpler option: route the IP-sensitive steps of your workflow through a static IP proxy. Your workflow runs on GitHub's hosted runners as usual. When it hits the step that needs a whitelisted IP, it routes that traffic through QuotaGuard.

HTTP/HTTPS Requests

For deployment API calls, webhook triggers, or any HTTP request that needs a static IP:

- name: Deploy to staging
  env:
    HTTPS_PROXY: ${{ secrets.QUOTAGUARD_URL }}
    HTTP_PROXY: ${{ secrets.QUOTAGUARD_URL }}
  run: |
    curl -X POST https://staging.internal.company.com/deploy \
      -H "Authorization: Bearer ${{ secrets.DEPLOY_TOKEN }}"

Set QUOTAGUARD_URL as a repository secret. The HTTP_PROXY and HTTPS_PROXY environment variables tell curl (and most HTTP clients) to route through the proxy. The staging server sees your two static IPs.

Using a Proxy in Python or Node Steps

If your deployment step runs a script rather than a curl command:

- name: Run deployment script
  env:
    QUOTAGUARD_URL: ${{ secrets.QUOTAGUARD_URL }}
  run: python deploy.py

In your script, use the proxy:

import os
import requests

proxy_url = os.environ.get('QUOTAGUARD_URL')
proxies = {'http': proxy_url, 'https': proxy_url}

response = requests.post(
    'https://staging.internal.company.com/deploy',
    json={'version': '1.2.3'},
    proxies=proxies
)

Database Migrations

If your workflow runs database migrations against a production or staging database that requires IP whitelisting, you have two options.

For databases that accept connections over HTTP (some managed database services offer HTTP APIs), use the proxy as shown above.

For direct TCP connections (PostgreSQL, MySQL), use QGTunnel. Add the QGTunnel binary to your repository and wrap your migration command:

- name: Run database migrations
  env:
    QUOTAGUARDSTATIC_URL: ${{ secrets.QUOTAGUARD_URL }}
  run: |
    bin/qgtunnel python manage.py migrate

QGTunnel opens a local socket, routes the TCP traffic through the static IP, and your database sees a whitelisted address. Your connection string doesn't change if you're using transparent mode.

SSH/SCP Deployments

For teams that deploy by SSHing into a server or SCPing files to a server with IP-based access control, route through QuotaGuard's SOCKS5 proxy:

- name: Deploy via SCP
  env:
    QUOTAGUARD_URL: ${{ secrets.QUOTAGUARD_URL }}
  run: |
    # Extract SOCKS5 proxy details from QUOTAGUARD_URL
    # Use ProxyCommand with ssh/scp
    scp -o ProxyCommand="nc -X 5 -x $SOCKS_HOST:$SOCKS_PORT %h %p" \
      ./build.tar.gz deploy@staging.company.com:/releases/

Selective Proxying

Most steps in a CI/CD pipeline don't need a static IP. Installing dependencies, running tests, building artifacts. Those can run directly on the hosted runner.

Only route the specific steps that touch firewalled resources through the proxy. This keeps your pipeline fast and avoids unnecessary proxy bandwidth.

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

      - name: Install dependencies
        run: npm install

      - name: Run tests
        run: npm test

      - name: Build
        run: npm run build

      # Only this step needs the static IP
      - name: Deploy to firewalled staging
        env:
          HTTPS_PROXY: ${{ secrets.QUOTAGUARD_URL }}
        run: |
          curl -X POST https://staging.internal.company.com/deploy \
            -d @build-manifest.json

Storing the Proxy URL

Add your QuotaGuard connection URL as a GitHub Actions secret:

1. Go to your repository Settings.
2. Click Secrets and Variables, then Actions.
3. Add a new repository secret named QUOTAGUARD_URL.
4. Paste your connection URL from the QuotaGuard dashboard.

The URL contains your credentials, so it should always be stored as a secret, never hardcoded in workflow files.

Getting Started

Sign up for QuotaGuard Static. Add the proxy URL as a GitHub Actions secret. Use HTTP_PROXY/HTTPS_PROXY environment variables for HTTP requests, or QGTunnel for TCP connections.

Test from a workflow step with:

- name: Verify static IP
  env:
    HTTPS_PROXY: ${{ secrets.QUOTAGUARD_URL }}
  run: curl https://ip.quotaguard.com

QuotaGuard Static starts at $19/month. If you need end-to-end encryption for compliance, QuotaGuard Shield starts at $29/month.

QuotaGuard Static IP Blog

Practical notes on routing cloud and AI traffic through Static IPs.

Reliability Engineered for the Modern Cloud

For over a decade, QuotaGuard has provided reliable, high-performance static IP and proxy solutions for cloud environments like Heroku, Kubernetes, and AWS.

Get the fixed identity and security your application needs today.