NAT Gateway: Give Private Servers Outbound Internet on a Shared IP
A NAT Gateway lets servers that have no public IP still reach the internet for updates, package installs, API calls, and webhooks, all through one shared public address. You attach it to a private network, and every server on that network can go out to the internet through it while staying invisible from the outside.
It's the standard pattern for private database and app tiers, locked-down build/CI boxes, and any fleet you want to keep off the public internet without cutting off outbound access.
How it works
You create a NAT Gateway on an existing private network. We provision a small managed gateway, give it a public IPv4 and IPv6 plus a private IP inside your network, and automatically add a default route (0.0.0.0/0) on the network that points at that private IP. From then on, any server whose traffic follows that route sends its outbound packets to the gateway, which rewrites the source to its own public IP (source NAT) and forwards them out; replies come back the same way. Many private servers share the gateway's single public IP for egress, and nothing reaches them from the internet unless you set that up separately. You manage all of it in the dashboard or over the API.
Before you start
- You need an existing private network first. If you don't have one, create it (see the Private Networks guide); the gateway attaches to it by
network_id. - In the dashboard: my.cubepath.com → NAT Gateway.
- Over the API: base URL
https://api.cubepath.com, authenticate withAuthorization: Bearer <token>(scopesnat_gateway:read/nat_gateway:write), and addX-Requested-With: XMLHttpRequeston writes. Get a token under Account → API Tokens. - Your organization must be verified, not suspended, and carry a positive balance (a NAT Gateway is a billed resource).
Create a NAT Gateway
Pick a plan and the network it should serve:
curl -X POST https://api.cubepath.com/nat-gateway/ \
-H "Authorization: Bearer $CUBEPATH_TOKEN" \
-H "X-Requested-With: XMLHttpRequest" \
-H "Content-Type: application/json" \
-d '{
"name": "egress-nat",
"label": "Production egress",
"plan_name": "nat.small",
"network_id": 42
}'
What you get back, and what happens next:
- A public IPv4 and a public IPv6 are allocated from the network's location. Both must be in stock or the request is rejected cleanly before anything is created.
- The gateway reserves a private IP inside the network (it can't be
.0,.1, or the broadcast). - A default route
0.0.0.0/0is added to the network automatically, pointing at the gateway's private IP, so your private servers start using it for egress. - The gateway starts in
deployingand flips toactiveonce provisioning finishes. List plans first withGET /nat-gateway/plans.
There's one NAT Gateway per private network. The gateway lives in the same project and location as its network, inferred automatically (or pass project_id and it must match the network's).
What this does to your servers
Once the gateway is active, any server attached to that private network that follows the default route reaches the internet through it and appears to remote services as the gateway's public IPv4. That's the point: a private-only database server can apt update or call a payment API without ever having its own public IP.
The default route is managed for you. You'll see it in the network's route list, but you can't delete it directly; deleting the NAT Gateway removes it. If you need more specific routing (send only certain CIDRs through the gateway, keep the rest local), add your own narrower routes on the network alongside it.
Plans and billing
Each plan sets the gateway's throughput and capacity:
| Plan attribute | Meaning |
|---|---|
bandwidth_mbps | Throughput ceiling for traffic through the gateway |
connections_per_second | New-connection rate the gateway sustains |
price_per_hour | What it costs while it exists |
Billing is hourly or monthly, following your project's billing type, and accrues from the moment the gateway is created until you delete it. Check current spend with the monthly_charges field on the gateway, and traffic with GET /nat-gateway/{uuid}/bandwidth-usage or the live GET /nat-gateway/{uuid}/metrics. A gateway also counts toward your combined VPS + Load Balancer + NAT Gateway resource limits (RAM, CPU, storage).
What this doesn't do
- It's not a load balancer. It gives servers a shared way out; it doesn't distribute incoming traffic. For inbound traffic across servers, use a Load Balancer.
- It's outbound NAT, not inbound port forwarding. By default nothing from the internet can open a connection to your private servers through it. To expose a service, put a public IP or Load Balancer on it directly.
- One per network, one location. A gateway serves a single private network in a single location. Different networks or locations each need their own.
API reference
GET /nat-gateway/plans List available plans. (scope: nat_gateway:read)
GET /nat-gateway/ List your NAT Gateways. (scope: nat_gateway:read)
GET /nat-gateway/{uuid} Get one gateway (status, IPs, charges). (scope: nat_gateway:read)
POST /nat-gateway/ { name, plan_name, network_id } Create a gateway. (scope: nat_gateway:write)
PATCH /nat-gateway/{uuid} { name, label } Rename a gateway. (scope: nat_gateway:write)
POST /nat-gateway/{uuid}/resize { plan_name } Change plan. (scope: nat_gateway:write)
POST /nat-gateway/{uuid}/move-to-project { project_id } Move to another project. (scope: nat_gateway:write)
POST /nat-gateway/{uuid}/protection { enabled } Toggle deletion protection. (scope: nat_gateway:write)
GET /nat-gateway/{uuid}/metrics Live bandwidth metrics. (scope: nat_gateway:read)
GET /nat-gateway/{uuid}/bandwidth-usage Month-to-date traffic. (scope: nat_gateway:read)
DELETE /nat-gateway/{uuid} Delete it (frees IPs, removes route). (scope: nat_gateway:write)
All requests authenticate with Authorization: Bearer <token> (or X-API-Key). Write requests also need X-Requested-With: XMLHttpRequest.
