Skip to content
Fixedmark
Integration · Automation and CI

GitHub Actions Static IP for Allowlisted Calls

GitHub-hosted runners get a different IP from large shared ranges on every job. To reach an allowlisted server, set `HTTPS_PROXY` from a secret on the specific steps that need it. curl, Python requests, and Go read it automatically, Node does with `NODE_USE_ENV_PROXY=1`, and the server sees only your dedicated Fixedmark pair.

Why GitHub-hosted runners change IP

Each job gets a fresh virtual machine. Linux and Windows runners run in Azure, and GitHub lists their address ranges under the actions key of its meta API. The list covers thousands of ranges shared with every GitHub user, changes weekly, and GitHub itself does not recommend using it as an allowlist.

GitHub's native options

GitHub offers larger runners with static IP address ranges, but only for organizations on GitHub Enterprise Cloud. They are Linux and Windows only, billed per minute at larger-runner rates, with up to 10 static-IP runner pools by default. Azure private networking, available on Team and Enterprise Cloud, runs hosted runners inside your own Azure virtual network, where you control egress. Self-hosted runners on a server with a fixed IP are the third route, at the cost of maintaining that server.

These make sense if most of your CI must originate from a fixed address. If only a deploy step or a nightly sync needs it, scoping a proxy to that step is simpler and keeps standard runners on any plan.

Sources for GitHub Actions pricing

Checked October 2026. Confirm current details on the vendor's site before you decide. Prices and limits change.

Set up a static IP on GitHub Actions

Set the proxy on steps, not on the job. That way checkout, caches, and artifact uploads go direct and do not count against your bandwidth.

Fixedmark is in early access. Proxy URLs are issued at launch. Join early access to get yours when your region opens.

Before you start

  • A repository with Actions enabled, on any GitHub plan.
  • A Fixedmark proxy URL (https://APP_ID:TOKEN@mum.egress.fixedmark.com:443) and the two IPs of your pair. Both are issued at launch. Join early access to get them.
  • Admin access to the repository or organization to add secrets.
  • Access to the partner's or database's allowlist, or a contact who can add two IPv4 addresses for you.

Steps

  1. 1
    Add the repository secretUnder Settings, Secrets and variables, Actions, add FIXEDMARK_PROXY_URL. Use an environment secret if only production deploys should have it.
  2. 2
    Set HTTPS_PROXY on the stepIn each step that calls the allowlisted server, add an env entry that sets HTTPS_PROXY from secrets.FIXEDMARK_PROXY_URL. Add NO_PROXY for local services.
  3. 3
    Handle Node.js explicitlyNode's built-in fetch ignores HTTPS_PROXY unless NODE_USE_ENV_PROXY=1 is set. That needs Node 22.21+ or 24+. On older Node, pass the URL to undici's ProxyAgent.
  4. 4
    Verify in the logRun the curl check in the proxied step. It prints one of your Fixedmark IPs. GitHub masks the secret in logs.
jobs:
  sync:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v5   # direct, no proxy

      - name: Call allowlisted partner API
        env:
          HTTPS_PROXY: ${{ secrets.FIXEDMARK_PROXY_URL }}
          NO_PROXY: localhost,127.0.0.1
        run: |
          curl -fsS https://fixedmark.com/api/ip   # prints a Fixedmark IP
          curl -fsS -H "Authorization: Bearer ${{ secrets.PARTNER_API_KEY }}" \
            https://api.partner.example/v1/orders

Verify the egress IP on GitHub Actions

Check the IP before you send it to a partner. Put the curl check at the top of the proxied step. With HTTPS_PROXY set, plain curl https://fixedmark.com/api/ip uses it. The endpoint https://fixedmark.com/api/ip returns the caller's IP as plain text, and the What's my IP tool shows the same thing in a browser.

The proxied call should print one of your two Fixedmark IPs every time. The direct call should print a different address. If both print the same platform IP, the client is not using the proxy.

# Needs curl 7.52 or later for an https:// proxy URL.
# Prints the IP the destination sees. Run it a few times:
# you should only ever see the two IPs of your pair.
curl -sS --proxy "$FIXEDMARK_PROXY_URL" https://fixedmark.com/api/ip

# Same check over SOCKS5, the path database drivers use.
curl -sS --proxy "$FIXEDMARK_SOCKS_URL" https://fixedmark.com/api/ip

# Without the proxy, for comparison. This is the platform's own IP.
curl -sS https://fixedmark.com/api/ip

Databases from Actions

Migrations against an IP-restricted database are the most common case. Run bm tunnel 5432:db.example.com:5432 & (planned for launch) in a step, then run your migration tool against 127.0.0.1 in the next step of the same job. TLS stays end to end. Drivers with SOCKS5 support can use FIXEDMARK_SOCKS_URL instead. See Postgres and MySQL allowlists.

# Forward local port 5432 to the database through your Fixedmark IPs.
# bm tunnel is planned for launch; flags are not final.
bm tunnel 5432:db.example.com:5432 &

# Point the driver at the local end of the tunnel.
DATABASE_URL="postgres://app:secret@127.0.0.1:5432/app?sslmode=require"

Common errors and fixes

The secret is empty in pull requests from forks

GitHub does not pass secrets to workflows triggered from forks. That is the safe default. Run the proxied step only on push or after review.

ssh: connect to host ... Connection timed out during deploy

SSH does not read HTTPS_PROXY. Use the SOCKS5 ProxyCommand with ncat shown above, or the tunnel.

407 Proxy Authentication Required

The proxy did not get valid credentials. Check that the env var holds the full URL with APP_ID:TOKEN@, with no quotes or trailing newline. If the token contains @, :, or /, URL-encode it. Some clients drop credentials from the URL: pass them separately (Deno's basicAuth, axios proxy.auth) or switch to undici's ProxyAgent, which reads them from the URL.

TLS errors to the proxy: wrong version number, EPROTO, Proxy CONNECT aborted, or unable to connect to proxy

The client does not support an https:// proxy URL and is speaking plain HTTP to port 443. Upgrade it: curl 7.52+, urllib3 1.26+ (requests), httpx 0.26+, undici ProxyAgent, Go 1.10+. In Ruby, use Typhoeus: Net::HTTP and Faraday's default adapter cannot tunnel HTTPS through a TLS proxy. For older axios releases, set proxy: false and pass https-proxy-agent as httpsAgent. Java's built-in HttpClient cannot speak TLS to a proxy at all. If you cannot upgrade, use the SOCKS5 URL.

ETIMEDOUT or ECONNRESET to the partner, or a 403 from the partner

The proxy connected, but the destination dropped you. Usually only one IP of the pair is on the allowlist, or the partner has not applied the change yet. Add both IPs. If a destination allowlist is set on your Fixedmark token, check the host and port are on it.

The IP check prints the platform's IP, not a Fixedmark IP

The request went direct. Node's built-in fetch ignores HTTPS_PROXY unless NODE_USE_ENV_PROXY=1 is set (Node 22.21+ and 24+). Many SDKs ignore proxy env vars too. Pass the proxy to the client explicitly, as in the snippets above.

429 or 407 with an X-Proxy-Error: quota_exceeded header

Planned behavior when you pass your plan's soft limit. Check usage in the dashboard or raise the plan.

Database driver has no proxy option

node-postgres, mysql2, psycopg, and most ORMs cannot use an HTTP proxy. Use a SOCKS5-capable driver with FIXEDMARK_SOCKS_URL, or run bm tunnel where the platform allows a second process.

Gotchas on GitHub Actions

SSH deploys (ssh, rsync, scp) do not read HTTPS_PROXY. Use the tunnel, or an SSH ProxyCommand with ncat, which supports SOCKS5 with a username and password. OpenBSD nc does not send SOCKS5 credentials.

  • Workflows from forks do not receive secrets, so pull requests from forks cannot use the proxy.
  • Setting HTTPS_PROXY for the whole job also proxies actions/cache and artifact uploads. Keep it on the steps that need it.

Frequently asked questions

Do GitHub Actions runners have static IPs?

Standard GitHub-hosted runners do not. They use large, shared ranges that change. Larger runners with static IP ranges need GitHub Enterprise Cloud.

Should I set HTTPS_PROXY for the whole job?

No. Set it on the steps that need a fixed IP. Job-wide, checkout, caches, and artifact uploads would also go through the proxy and use your bandwidth.

Why does my Node script ignore HTTPS_PROXY?

Node's built-in fetch reads proxy environment variables only when NODE_USE_ENV_PROXY=1 is set, on Node 22.21+ or 24+. On older Node, pass the proxy URL to undici's ProxyAgent as the dispatcher option.

Can I run database migrations through the static IP?

Yes. Start the bm tunnel CLI in one step and run migrations against 127.0.0.1 in the next, or use a driver that supports SOCKS5.

Fix your egress IP.

Fixedmark is in early access. Join the list to get a dedicated IP pair for GitHub Actions when your region opens.