Providing Outbound-Only Internet Access in IBM Cloud VPC with a Zonal Public Gateway
Learn how to give private IBM Cloud VPC subnets outbound-only internet access using a zonal public gateway, with routing, security group, and ACL configuration steps.
03 Aug 2025, 21:07 UTC

The problem: private instances that still need the internet
Instances in a private IBM Cloud VPC subnet often need outbound internet access—to apply operating system patches, download packages, or pull container images—but assigning floating IPs or public IP addresses gives them an inbound attack surface you may not want. A zonal public gateway provides outbound-only network address translation (NAT) for a subnet. The instance keeps its private address, the internet cannot initiate connections to it, and you avoid managing per-instance public addresses.
Desired outcome
- Instances in a private subnet can reach the internet for OS updates and package downloads.
- No floating IP or public IP is attached to the instance.
- Inbound connections from the internet cannot reach the instance.
Prerequisites
- An IBM Cloud VPC and a subnet located in a single zone.
- A test instance in that subnet with no floating IP assigned.
- IAM permissions to create public gateways, attach them to subnets, and modify routing tables, security groups, and network ACLs.
- Control of the subnet's security group and network ACL.
Procedure: create and attach a zonal public gateway
A public gateway is a zonal resource. It must exist in the same zone as the subnet it serves. Run the following commands from a terminal where the IBM Cloud CLI is installed and you are logged in to the correct account and region. Verify the exact command names and flags against current IBM Cloud documentation before running them in production, because CLI syntax and defaults change over time.
# Create a public gateway in the subnet's zone
ibmcloud is public-gateway-create outbound-gateway \
--vpc <vpc-id> \
--zone <zone>
# Attach the gateway to the private subnet
ibmcloud is subnet-add-public-gateway <subnet-id> <gateway-id>
# Inspect the subnet to confirm attachment and routing
ibmcloud is subnet <subnet-id>
Replace <vpc-id>, <zone>, <subnet-id>, and <gateway-id> with your actual identifiers. If the subnet uses a custom route table rather than the VPC default, confirm that the effective routing table contains a 0.0.0.0/0 route whose next hop is the public gateway, and add it if it is missing.
Security group and ACL configuration
Security groups are stateful: if you allow an outbound request, the return traffic is automatically permitted. For a private instance that only needs outbound HTTPS, allow egress on TCP port 443 and leave inbound rules at their restrictive defaults.
Network ACLs are stateless. They evaluate each packet independently, so an outbound request and its reply are separate decisions. If you replace the default ACL, you must explicitly allow both directions. A minimal ACL pair for outbound HTTPS looks like this:
| Direction | Protocol/Port | Source/Destination | Action |
|---|---|---|---|
| Outbound | TCP 443 | 0.0.0.0/0 | Allow |
| Inbound | TCP 1024–65535 | 0.0.0.0/0 | Allow |
The inbound rule permits return traffic on ephemeral ports. Without it, outbound connections will fail even though the security group allows them.
Expected checks
- Gateway status: List public gateways and inspect the subnet. The gateway should show as attached and stable, and it must be in the same zone as the subnet.
- No public address: Inspect the instance's network interfaces. The primary interface should have no floating IP.
- Outbound success: From the instance, run an outbound request such as
curl -I https://example.comor a package-manager update. The request should succeed. - Inbound isolation: From a host outside the VPC, attempt to reach the instance. Because the instance has no public address and the gateway is outbound-only, the connection should fail.
Diagnostic decision: default ACL versus custom ACL
If curl succeeds when the subnet uses the default ACL but fails after you apply a custom ACL, the most likely cause is the stateless nature of ACLs. The default ACL allows both outbound requests and return traffic. A custom ACL that only allows outbound TCP 443 will drop the reply packets. Add the inbound ephemeral-port rule shown above and retest.
Recovery options
- Stop egress: Detach the public gateway from the subnet or remove the
0.0.0.0/0route from the effective route table. Outbound internet access stops immediately. - Gateway deleted: If the gateway is deleted, create a new one in the same zone and reattach it to the subnet. Gateways are zonal, so a gateway in another zone cannot serve this subnet.
- Break-glass access: If you need temporary inbound access for troubleshooting, assign a floating IP to the instance, complete the task, and remove the floating IP immediately afterward. Do not leave it attached.
Limitations and current verification
- Zonal scope: A public gateway serves only subnets in its zone. Multi-zone architectures require one gateway per zone.
- Outbound only: The feature does not support inbound services. Use a floating IP, load balancer, or VPN for inbound connectivity.
- NAT address visibility: External allowlists may observe the gateway's NAT address. Confirm that the address is stable before hard-coding it in partner firewall rules.
- Changing interfaces: IBM Cloud command names, limits, and defaults change. Verify current CLI and API behavior in a non-production account before rolling this out.
Practical verification
After configuration, confirm the result by running an outbound request from the instance and verifying it succeeds, while simultaneously confirming that the instance has no floating IP and cannot be reached from the internet. This combination proves the gateway is working as intended: outbound permitted, inbound denied.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.