A Static IP for GitHub Actions
GitHub-hosted runners egress from ranges shared with every GitHub Actions user on the platform, so allow-listing them means allow-listing everybody's CI, including anybody who forks your workflow patterns. GitHub's own fix is static IP ranges on larger runners, which needs Team or Enterprise. A self-hosted runner is free and is the right answer more often than people expect. A dedicated address is worth it when you want hosted runners and one fixed source.
Why the published ranges are not an allow-list
GitHub publishes the address ranges its hosted runners use — fetch them from https://api.github.com/meta under the actions key. It is tempting to paste those into a firewall and call the problem solved. Look at the size of what you just pasted first.
curl -s https://api.github.com/meta | jq '.actions | length'
Those ranges cover thousands of addresses across Azure regions, and they are shared by every GitHub Actions workflow running anywhere in the world. Allow-listing them does not admit your CI. It admits all CI — any GitHub user who can run a workflow is inside your firewall rule. For a staging box that may be an acceptable risk you have chosen deliberately. For a production database or a partner endpoint it is not an allow-list in any meaningful sense, and a reviewer who understands what the range is will say so.
They also change. GitHub updates the published set, and a firewall rule pinned to a copy you pasted last year will start failing without anything on your side having changed.
GitHub's own answer: larger runners with static IPs
GitHub supports assigning unique, static public IP ranges to larger runners: in the runner's networking settings, enable the option to assign a static IP range, and the addresses become yours to allow-list. This is first-party, well integrated, and it is the correct answer if it is available to you.
Larger runners require a Team or Enterprise plan, and are billed per-minute at higher rates than standard hosted runners. If you are already on Team or Enterprise and using larger runners, turn this on and stop reading — nothing below improves on it.
The free answer most people skip: a self-hosted runner
A self-hosted runner is a machine you control, so its outbound address is whatever that machine's address is. No add-on, no per-minute premium, no plan tier. If you already have a server, this costs nothing.
We are saying this plainly because it is frequently the right answer and it competes with us: if the workflow that needs the fixed address is a deploy or a migration that runs a few times a day, a small self-hosted runner is cheaper and simpler than anything else on this page, ours included.
The honest counter-arguments, which are also real:
- Security posture changes. A self-hosted runner executes workflow code on your machine. On a public repository this is genuinely dangerous — GitHub documents it — because a pull request from a stranger can run code on your runner. Self-hosted runners suit private repositories.
- It is a machine you maintain, patch, and keep online, and when it is down your pipeline is down.
When a dedicated address is the better trade
The case for an address you hold is narrower and worth stating precisely. It fits when you want to keep using GitHub-hosted runners — ephemeral, maintained by GitHub, safe for public repositories — but need one specific step to leave from a known source.
Attach a TunnelNet address to a small always-on box and route the sensitive step through it: the migration that talks to the production database, the deploy that reaches a firewalled server, the call to a partner API. The rest of the workflow runs on GitHub's runners exactly as before.
What the far end sees is your dedicated address from 23.187.152.0/24, announced by AS396500. It is not shared with other CI users, it does not change when GitHub rotates its ranges, and it is the same address whether the call comes from CI, from a server, or from a laptop — which is the part that tends to decide it. One allow-list entry can cover your CI, your production backend and your on-call engineer's machine.
Honest caveats, same as everywhere else on this site:
- It is a hop and a machine you keep running. If it is down, that workflow step fails.
- It suits named endpoints, not “all traffic from CI”.
Choosing between them
- Larger runners with static IPs if you are on Team or Enterprise. First-party and least work.
- A self-hosted runner if the repository is private and you already have a machine. Free, and hard to beat.
- A dedicated address if you need hosted runners for public repositories or fleet reasons, or if the same source address has to serve CI and your other systems.
- The published ranges essentially never, unless the thing behind the firewall genuinely does not mind all of GitHub reaching it.
Verify the source address before you file it
Add a step that prints the address the far end will actually see, from the same job that makes the real call:
curl -4 https://api.ipify.org
Check it a second way (curl -4 https://ifconfig.co), and re-run the workflow before you file the address — on hosted runners a single observation tells you about one runner, not about the next one. A mis-filed address fails as a total denial at the far end, not as a warning.
What this costs with us
A dedicated address is $20/month on TunnelNet Full, inbound and outbound on the same address, attached to a machine you already have. TunnelNet Business is $100/month for the same address with a written 8-working-hour response commitment (09:00–17:00 US Central, Monday to Friday), onboarding done with a person who verifies the source address from outside our network before you file it, and our measured uptime published — incidents included.
Plainly, because you are about to put a partner integration on this: we have no SLA and will not offer one until we have six months of measured history, 21 February 2027 at the earliest. A hub failure that withdraws routes takes about 25 seconds to recover, measured — and a hub that stays up while it stops forwarding is not failed over automatically at all. GitHub will quote you better availability numbers than that, and they will be true. Weigh it against what the address itself is worth to you.
Static IP for your platform
The same question, answered for each platform it comes up on most. Every one of them leads with that platform's own native or free answer:
- AWS Lambda — VPC and NAT Gateway, and what that really costs
- Vercel — $100/month per project, and Vercel documents the IPs as shared
- Netlify Functions — no list exists — what to try before building anything
- Supabase Edge Functions — Supabase documents that there is no static egress IP
- Heroku — Private Spaces, proxy add-ons, or an address you hold
- Render — shared by default, genuinely dedicated on Pro
- Railway — a Pro-plan toggle, and the “may be shared” caveat
- Zapier — included on Professional, absent on Free
And the general case, if your platform is not listed: