Home / OCI

OCIHow-toBeginner

Introduction to the OCI Service Gateway: reach Object Storage and OCI services from private subnets without internet

What an OCI Service Gateway is, the difference between the two service CIDR labels, and how to create one, route to it and lock Object Storage buckets to your VCN, with OCI CLI commands.

Deepak Bhardwaj4 min read

Applies toOCI Networking (VCN, route tables, security lists/NSGs), Service Gateway, Object Storage, OCI CLI 3.x

The problem it solves

Instances in a private subnet have no public IP and no route to an Internet Gateway. They still need to:

  • Read and write Object Storage (backups, logs, data files).
  • Install OS updates from the OCI YUM mirrors.
  • Call OCI service APIs (Monitoring, Logging, Vault).

A NAT Gateway would work, but traffic leaves through public endpoints and every instance needs internet egress. A Service Gateway gives private subnets a direct path to Oracle Services Network inside OCI, with no internet involved.

Two service labels: pick the right one

When you create a Service Gateway you choose one of two "services" (CIDR labels). Names include the region key:

Label (example for Mumbai) Covers Use when
OCI BOM Object Storage Object Storage only You only need buckets
All BOM Services In Oracle Services Network Object Storage plus other OCI services and the regional YUM mirrors You want OS updates and OCI APIs privately too

Most teams pick All Services. List what your region offers:

oci network service list --query 'data[].{name:name, id:id, cidr:"cidr-block"}' --output table

Tip

A Service Gateway only reaches services in the same region. For Object Storage in another region you still need NAT, or replication into the local region.

Step 1: Create the Service Gateway

COMPARTMENT=ocid1.compartment.oc1..aaaa...
VCN=ocid1.vcn.oc1.ap-mumbai-1.aaaa...
SVC_ID=$(oci network service list \
  --query "data[?contains(name,'All')].id | [0]" --raw-output)

oci network service-gateway create \
  --compartment-id $COMPARTMENT --vcn-id $VCN \
  --services "[{\"serviceId\":\"$SVC_ID\"}]" \
  --display-name sgw-prod

One Service Gateway per VCN is enough.

Step 2: Add a route rule in the private subnet's route table

The destination is the service CIDR label, not an IP range:

SGW=$(oci network service-gateway list --compartment-id $COMPARTMENT --vcn-id $VCN \
  --query 'data[0].id' --raw-output)
SVC_CIDR=$(oci network service list --query "data[?contains(name,'All')].\"cidr-block\" | [0]" --raw-output)

oci network route-table update --rt-id <private-route-table-ocid> \
  --route-rules "[{\"destination\":\"$SVC_CIDR\",\"destinationType\":\"SERVICE_CIDR_BLOCK\",\"networkEntityId\":\"$SGW\"},
                  {\"destination\":\"0.0.0.0/0\",\"destinationType\":\"CIDR_BLOCK\",\"networkEntityId\":\"<nat-gateway-ocid>\"}]" \
  --force

Warning

route-table update --route-rules replaces the whole rule list. Get the current rules first (oci network route-table get --rt-id ...) and include every rule you want to keep, or you'll drop the NAT or DRG route.

With both rules in place, traffic to OCI services goes through the Service Gateway and everything else to the internet goes through NAT.

Step 3: Allow it in security rules

Egress from the private subnet must allow HTTPS to the service label. In a security list or NSG, add an egress rule:

  • Destination type: Service
  • Destination service: All BOM Services In Oracle Services Network
  • Protocol: TCP, destination port 443

If your egress is already "all traffic to 0.0.0.0/0", nothing extra is needed.

Step 4: Test from a private instance

# Instance principal auth (needs a dynamic group + policy) or a config file
oci os ns get --auth instance_principal
oci os object list --bucket-name app-backups --auth instance_principal --limit 5

# OS updates through the regional mirror (Oracle Linux)
sudo dnf makecache

If oci os ns get hangs, check the route table and security rules. If it returns NotAuthorizedOrNotFound, networking is fine and the problem is IAM.

Step 5: Restrict a bucket to your VCN (optional)

You can make a bucket readable only from your VCN through the Service Gateway with an IAM policy condition:

Allow group AppOperators to manage objects in compartment app-prod
  where all {target.bucket.name = 'app-backups', request.vcn.id = 'ocid1.vcn.oc1.ap-mumbai-1.aaaa...'}

Requests from outside the VCN (laptops, other VCNs) no longer match the Allow and are refused. Keep a separate policy for admins so you can still manage the bucket from the console.

Service Gateway vs NAT Gateway vs private endpoint

Need Use
Private subnet → Object Storage / OCI services in same region Service Gateway
Private subnet → internet (GitHub, Docker Hub, external APIs) NAT Gateway
On-prem → Object Storage privately over FastConnect Service Gateway with a DRG transit route (transit routing)
Private IP address for a specific service resource (for example Autonomous DB) Private endpoint

Prevent problems later

  • Add a Service Gateway to every VCN in your landing zone template, routed from all private subnets.
  • Move bulk backup and log traffic off NAT; it's simpler and avoids NAT throughput limits.
  • Keep route table changes in Terraform so a manual --route-rules update can't silently delete routes.
  • Use request.vcn.id conditions for sensitive buckets.