oraclecloud-core-workflow-b

v2026.09.24

Build OCI networking from scratch — VCN, subnets, gateways, and security rules. Use when creating a new VCN, debugging connectivity issues, or setting up security lists and NSGs. Trigger with "oci networking", "vcn setup", "security list", "nsg rules", "oci subnet".

GitHub
Install command
npx skhub add jeremylongshore/oraclecloud-core-workflow-b
Markdown
SKILL.md

OCI Networking — VCN, Subnets & Security Rules

Overview

Build a working OCI network from scratch using the Python SDK. OCI networking (VCN, subnets, security lists, NSGs, gateways) has more moving parts than AWS VPC. A misconfigured security list silently drops traffic with no error — just timeouts. This skill creates a complete network topology with public and private subnets, internet and NAT gateways, route tables, and Network Security Groups (NSGs).

Purpose: Build a production-ready VCN with proper routing and security rules that actually works on first deploy.

Prerequisites

  • OCI Python SDK — pip install oci
  • Config file at ~/.oci/config with fields: user, fingerprint, tenancy, region, key_file
  • IAM policy — Allow group Developers to manage virtual-network-family in compartment <name>
  • Python 3.8+

Instructions

Step 1: Create the VCN

import oci

config = oci.config.from_file("~/.oci/config")
network = oci.core.VirtualNetworkClient(config)

vcn = network.create_vcn(
    oci.core.models.CreateVcnDetails(
        compartment_id=config["tenancy"],
        display_name="app-vcn",
        cidr_blocks=["10.0.0.0/16"],
        dns_label="appvcn",
    )
).data
print(f"VCN created: {vcn.id}")

Step 2: Create Internet Gateway and NAT Gateway

The internet gateway handles inbound/outbound traffic for public subnets. The NAT gateway gives private subnets outbound-only internet access.

# Internet Gateway (for public subnets)
igw = network.create_internet_gateway(
    oci.core.models.CreateInternetGatewayDetails(
        compartment_id=config["tenancy"],
        vcn_id=vcn.id,
        display_name="app-igw",
        is_enabled=True,
    )
).data

# NAT Gateway (for private subnets — outbound only)
nat = network.create_nat_gateway(
    oci.core.models.CreateNatGatewayDetails(
        compartment_id=config["tenancy"],
        vcn_id=vcn.id,
        display_name="app-nat",
    )
).data
print(f"IGW: {igw.id}\nNAT: {nat.id}")

Step 3: Create Route Tables

# Public route table — all traffic via internet gateway
public_rt = network.create_route_table(
    oci.core.models.CreateRouteTableDetails(
        compartment_id=config["tenancy"],
        vcn_id=vcn.id,
        display_name="public-rt",
        route_rules=[
            oci.core.models.RouteRule(
                network_entity_id=igw.id,
                destination="0.0.0.0/0",
                destination_type="CIDR_BLOCK",
            )
        ],
    )
).data

# Private route table — all traffic via NAT gateway
private_rt = network.create_route_table(
    oci.core.models.CreateRouteTableDetails(
        compartment_id=config["tenancy"],
        vcn_id=vcn.id,
        display_name="private-rt",
        route_rules=[
            oci.core.models.RouteRule(
                network_entity_id=nat.id,
                destination="0.0.0.0/0",
                destination_type="CIDR_BLOCK",
            )
        ],
    )
).data

Step 4: Create Network Security Group (NSG)

Use NSGs instead of security lists. NSGs attach to VNICs (per-instance) while security lists apply to entire subnets. NSGs are easier to manage and the OCI-recommended approach.

nsg = network.create_network_security_group(
    oci.core.models.CreateNetworkSecurityGroupDetails(
        compartment_id=config["tenancy"],
        vcn_id=vcn.id,
        display_name="app-nsg",
    )
).data

# Add ingress rules — SSH, HTTP, HTTPS
rules = [
    oci.core.models.AddSecurityRuleDetails(
        direction="INGRESS",
        protocol="6",  # TCP
        source="0.0.0.0/0",
        source_type="CIDR_BLOCK",
        tcp_options=oci.core.models.TcpOptions(
            destination_port_range=oci.core.models.PortRange(min=port, max=port)
        ),
        description=desc,
    )
    for port, desc in [(22, "SSH"), (80, "HTTP"), (443, "HTTPS")]
]

# Add egress rule — allow all outbound
rules.append(
    oci.core.models.AddSecurityRuleDetails(
        direction="EGRESS",
        protocol="all",
        destination="0.0.0.0/0",
        destination_type="CIDR_BLOCK",
        description="Allow all outbound",
    )
)

network.add_network_security_group_security_rules(
    network_security_group_id=nsg.id,
    add_network_security_group_security_rules_details=oci.core.models.AddNetworkSecurityGroupSecurityRulesDetails(
        security_rules=rules
    ),
)
print(f"NSG created with {len(rules)} rules: {nsg.id}")

Step 5: Create Public and Private Subnets

identity = oci.identity.IdentityClient(config)
ad = identity.list_availability_domains(compartment_id=config["tenancy"]).data[0].name

# Public subnet
public_subnet = network.create_subnet(
    oci.core.models.CreateSubnetDetails(
        compartment_id=config["tenancy"],
        vcn_id=vcn.id,
        display_name="public-subnet",
        cidr_block="10.0.1.0/24",
        route_table_id=public_rt.id,
        dns_label="pubsub",
        prohibit_public_ip_on_vnic=False,  # Allow public IPs
    )
).data

# Private subnet
private_subnet = network.create_subnet(
    oci.core.models.CreateSubnetDetails(
        compartment_id=config["tenancy"],
        vcn_id=vcn.id,
        display_name="private-subnet",
        cidr_block="10.0.2.0/24",
        route_table_id=private_rt.id,
        dns_label="privsub",
        prohibit_public_ip_on_vnic=True,  # No public IPs
    )
).data

print(f"Public subnet: {public_subnet.id}")
print(f"Private subnet: {private_subnet.id}")

Step 6: Verify Connectivity

# List all subnets in the VCN to confirm setup
subnets = network.list_subnets(
    compartment_id=config["tenancy"],
    vcn_id=vcn.id
).data

for s in subnets:
    print(f"{s.display_name} | {s.cidr_block} | Public IPs: {not s.prohibit_public_ip_on_vnic}")

Output

Successful completion produces:

  • A VCN with a /16 CIDR block and DNS resolution enabled
  • Internet gateway (public traffic) and NAT gateway (private outbound)
  • Separate route tables for public and private subnets
  • An NSG with SSH (22), HTTP (80), and HTTPS (443) ingress rules
  • Public and private subnets with correct routing

Error Handling

ErrorCodeCauseSolution
Not authorized404 NotAuthorizedOrNotFoundMissing IAM policy for virtual-network-familyAdd policy: Allow group X to manage virtual-network-family in compartment Y
CIDR overlap400 InvalidParameterSubnet CIDR conflicts with existing subnetUse non-overlapping /24 blocks within the VCN /16 range
Limit exceeded400 LimitExceededVCN or subnet limit reachedCheck limits in Console > Governance > Limits; request increase
Silent traffic dropN/ASecurity list or NSG missing ingress ruleCheck NSG rules — OCI drops unmatched traffic with no ICMP unreachable
Not authenticated401 NotAuthenticatedBad API key or configVerify ~/.oci/config key_file and fingerprint
Rate limited429 TooManyRequestsToo many API callsAdd backoff; OCI does not return Retry-After header

Debugging silent drops: If traffic times out, check in this order: (1) NSG ingress rules, (2) security list rules, (3) route table entries, (4) gateway exists and is enabled. OCI applies security lists AND NSGs — traffic must pass both.

Examples

Quick VCN list via CLI:

oci network vcn list \
  --compartment-id <OCID> \
  --query "data[*].{Name:\"display-name\",CIDR:\"cidr-blocks\"}" \
  --output table

Check NSG rules for debugging:

rules = network.list_network_security_group_security_rules(
    network_security_group_id=nsg.id
).data
for r in rules:
    print(f"{r.direction} | {r.protocol} | {r.source or r.destination} | {r.description}")

Resources

Next Steps

After networking is in place, launch instances with oraclecloud-core-workflow-a (use the subnet IDs from Step 5), or set up monitoring with oraclecloud-query-transform to watch network traffic metrics.

Discovery
Tags

No tags published for this skill.

Version
Latest version metadata

Version

v2026.09.24

Published

Sep 24, 2026

Category

Uncategorized

License

MIT

Source path

skills/.curated/oraclecloud-core-workflow-b

Default branch

main

Latest commit

e5a6c3b

Tree SHA

c2dc8e8