Skip to content

Origin allowlist

If your origin is reachable over the public internet, anyone who learns its address can send it a request directly and skip GraphPilot. Verifying the request signature catches that, but only after the request has arrived and been parsed. Refusing it at the network layer is the cheaper first line.

GraphPilot reaches your origin from a published set of IP ranges. Allow those at your origin’s firewall or load balancer, and nothing else needs to be open for GraphPilot to work.

In the portal, under Organization → Service → Settings → General, in the section the portal titles Origin allowlist. The page shows IPv4 and IPv6 separately, with a copy button for each family and one for the whole set. Copied values are one range per line, in CIDR notation, which is the form most firewalls and scripts split on.

The same set is on the GraphPilot API, which is what to read if you want to build the rule from a script:

query {
services(condition: { subdomain: "my-shop" }) {
ipRanges {
ipv4
ipv6
}
}
}

services returns a list, holding the one service with that subdomain. ipv4 and ipv6 are lists of ranges in CIDR notation. Reading the field needs the service:view permission, so an API key for a script needs nothing more.

The ranges are the same for every service in your organization today: they describe Fastly’s edge network, which GraphPilot runs on, not your service. Read them per service anyway; the field is per service so that this can change.

With shielding, only the shield location contacts your origin for most eligible requests, so far fewer edge nodes do. The ranges to allow stay the same, because the shield is part of the same network. Keep the whole set in your rule: when the shield is unreachable before a request is sent, the edge location falls back and reaches your origin directly, and requests that never go through the shield (subscriptions, other plain HTTP methods, and requests that skip the cache) always reach your origin from their own edge location.

The ranges are published by Fastly and they move when the network does: new ranges are added as capacity is added, and old ones are withdrawn. There is no version of this list that stays correct forever, and GraphPilot does not promise a fixed number of locations.

Two things follow from that:

  • GraphPilot does not notify you when it changes. There is no email, no webhook, and no entry you can subscribe to. The portal and the API always show the current set; nothing pushes the change to a rule you have already written.
  • A rule built once from a copy will eventually be wrong. The failure is one-sided and quiet: traffic from a newly added range is dropped by your firewall, so those requests fail to reach your origin while everything from the older ranges keeps working. What you see are origin connection failures on a fraction of traffic, not an obvious outage.

The way to stay correct is to re-read the set rather than to remember it:

  • Read ipRanges from the API on a schedule (daily is comfortably often enough) and reconcile the firewall rule from what it returns, in whatever form your firewall automates.
  • If you cannot automate it, put a recurring reminder against the portal page instead, and check it again whenever you are investigating origin connection failures that affect only part of your traffic.
  • Widen before you narrow: add new ranges as soon as they appear, and remove withdrawn ones afterwards. Removing first is what turns a routine change into failed requests.

Fastly also publishes the same list at api.fastly.com/public-ip-list if you would rather read it from the source. Reading it from GraphPilot and reading it from Fastly give the same answer today, and only the field on the GraphPilot API is kept working.

There is no mutual TLS to the origin today, and no per-service source address. If your threat model needs a source address that only your traffic uses, an allowlist will not give it to you.

An empty or unreachable list is not an instruction to close the firewall. If the portal cannot load the ranges, leave the existing rule in place and try again rather than narrowing it on a failed read.