2.1.5 VCN & private subnet (step-by-step in Terraform)
For this example, we will keep the the same child compartment "WildTestCompartment" from previous example VCN & public subnet (new compartment)
I suggest you read the previous example before continuing with this one.
Private subnet vs. Public subnet
As you might already notice in VCN &public subnet tutorial, when you assign a public subnet to your instance (with a public IP), in order to make possible the communication with the Internet (outbound and inbound traffic), you need to set-up an Internet Gateway, as well.
However, there are situations when one does not want the hosts/services to be accessed from the outside (inbound), and yet to still be able to access the Internet (outbound) for performing certain actions, such as updates.
In this scenario, your hosts will be provided a private subnet (and private IPs), along with a NAT Gateway.
Adapting your Terraform code
We have already discussed about what we need for a VCN &private subnet:
NAT gateway
private IP
For the public subnet, we have used the resource
oci core internet gateway
In the example for private subnet, we need to create a new terraform file, for configuring and setting up the NAT gateway for our compartment.
For this case, we will be using the resource
oci core nat gateway
Our
nat_gateway.tf
file has the following content:
root@deploymentmachine:/home/nat_example# more nat_gateway.tf
resource "oci_core_nat_gateway" "WildTestNATGateway" {
compartment_id = oci_identity_compartment.WildTestCompartment.id
display_name = "WildTestNATGateway"
vcn_id = oci_core_virtual_network.WildTestVCN.id
}
Next change, will be reflected on the
Route Table.
We are keeping the same resource
oci core route table
However, changes to be implemented on the routing rules consist in providing the Nat Gateway:
root@deploymentmachine:/home/nat_example# more route.tf
resource "oci_core_route_table" "WildTestRouteTable" {
compartment_id = oci_identity_compartment.WildTestCompartment.id
vcn_id = oci_core_virtual_network.WildTestVCN.id
display_name = "WildTestRouteTable"
route_rules {
destination = "0.0.0.0/0"
network_entity_id = oci_core_nat_gateway.WildTestNATGateway.id
}
}
... and the private IP
This change will be reflected when configuring the subnet.
The same resource will be used,
oci core subnet
.
If you read carefully the documentation, you will find the following information about "prohibit_public_ip_on_vnic"
prohibit_public_ip_on_vnic
- (Optional) Whether VNICs within this subnet can have public IP addresses. Defaults to false, which means VNICs created in this subnet will automatically be assigned public IP addresses unless specified otherwise during instance launch or VNIC creation[...]
. IfprohibitPublicIpOnVnic
is set to true, VNICs created in this subnet cannot have public IP addresses (that is, it's a private subnet).
Taking in consideration that piece of documentation, my "subnet.tf" file will have the following addition:
root@deploymentmachine:/home/nat_example# more subnet.tf | grep prohibit
prohibit_public_ip_on_vnic = true
The code example
Content of the folder nat_example:
root@deploymentmachine:/home/nat_example# tree -I '*tfstate|*.backup'
.
├── compartment.tf
├── dhcp_opt.tf
├── nat_gateway.tf
├── provider.tf
├── route.tf
├── security_list.tf
├── subnet.tf
├── variables.tf
└── vcn.tf
0 directories, 9 files
Content of
provider.tf
root@deploymentmachine:/home/nat_example# more provider.tf
provider "oci" {
tenancy_ocid = "ocid1.tenancy.oc1..aaaaaaaafaketenancyocidhahahah123234234"
user_ocid = "ocid1.user.oc1..aaaaaaafakeuserocidhahahah12312434"
private_key_path = "/root/.oci/oci_api_key.pem"
fingerprint = "xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx"
region = "eu-frankfurt-1"
}
Content of
variables.tf
root@deploymentmachine:/home/nat_example# more variables.tf
variable "compartment_ocid" {
default = "ocid1.tenancy.oc1..aaaaaaaa5u7673g6im7w7533shadcgbqxuzpcv6toqmb5yxzxigmeirt6hdq"
}
#for vcn block
variable "cidrblockz" {
type = list(string)
default = ["10.0.0.0/16"]
}
#for subnet
variable "cidrsubnet" {
default = "10.0.1.0/24"
}
# for ingress
variable "cidr_ingress" {
default = "10.0.0.0/16"
}
# for security list
variable "portz" {
default = [22,3306,33060]
}
Content of
compartment.tf
root@deploymentmachine:/home/nat_example# more compartment.tf
resource "oci_identity_compartment" "WildTestCompartment" {
compartment_id = var.compartment_ocid
description = "Compartment test for private subnet VCN"
name = "WildTestCompartment"
}
Content of
vcn.tf
root@deploymentmachine:/home/nat_example# more vcn.tf
resource "oci_core_virtual_network" "WildTestVCN" {
cidr_blocks = var.cidrblockz
compartment_id = oci_identity_compartment.WildTestCompartment.id
display_name = "WildTestVCN"
# for dns
dns_label = "WildTestVCN"
}
Content of
nat_gateway.tf
root@deploymentmachine:/home/nat_example# more nat_gateway.tf
resource "oci_core_nat_gateway" "WildTestNATGateway" {
compartment_id = oci_identity_compartment.WildTestCompartment.id
display_name = "WildTestNATGateway"
vcn_id = oci_core_virtual_network.WildTestVCN.id
}
Content of
route.tf
resource "oci_core_route_table" "WildTestRouteTable" {
compartment_id = oci_identity_compartment.WildTestCompartment.id
vcn_id = oci_core_virtual_network.WildTestVCN.id
display_name = "WildTestRouteTable"
route_rules {
destination = "0.0.0.0/0"
network_entity_id = oci_core_nat_gateway.WildTestNATGateway.id
}
}
Content of
subnet.tf
root@deploymentmachine:/home/nat_example# more subnet.tf
resource "oci_core_subnet" "WildTestSubnet"{
cidr_block = var.cidrsubnet
compartment_id = oci_identity_compartment.WildTestCompartment.id
vcn_id = oci_core_virtual_network.WildTestVCN.id
display_name = "WildTestSubnet"
prohibit_public_ip_on_vnic = true
# security list
security_list_ids = [oci_core_security_list.WildTestSecurityList.id]
# route table
route_table_id = oci_core_route_table.WildTestRouteTable.id
# dhcp
dhcp_options_id = oci_core_dhcp_options.WildTestDHCPOptions.id
# dns
dns_label = "WildTest"
}
Content for dhcp options,
dhcp_opt.tf
:
resource "oci_core_dhcp_options" "WildTestDHCPOptions" {
compartment_id = oci_identity_compartment.WildTestCompartment.id
vcn_id = oci_core_virtual_network.WildTestVCN.id
display_name = "WildTestDHCPOptions"
options {
type = "DomainNameServer"
server_type = "VcnLocalPlusInternet"
}
options {
type = "SearchDomain"
search_domain_names = ["wildtest.com"]
}
}
Content of security lists,
security_list.tf
:
root@deploymentmachine:/home/nat_example# more security_list.tf
resource "oci_core_security_list" "WildTestSecurityList" {
compartment_id = oci_identity_compartment.WildTestCompartment.id
display_name = "WildTestSecurityList"
vcn_id = oci_core_virtual_network.WildTestVCN.id
egress_security_rules {
stateless = false
protocol = "6"
destination = "0.0.0.0/0"
}
# apply ingress tcp rules for each port
# of variable portz
dynamic "ingress_security_rules" {
for_each = toset(var.portz)
content {
protocol = "6"
source = var.cidr_ingress
tcp_options {
max = ingress_security_rules.value
min = ingress_security_rules.value
}
}
}
#ingress_security_rules {
# stateless = false
## protocol = "6"
# source = var.cidr_ingress
#}
}
Deploying VCN &private subnet
As usual, for deploying, use the three main terraform commands:
terraform init
terraform plan
terraform apply
root@deploymentmachine:/home/nat_example# terraform apply
An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
+ create
[ ... snip ... ]
Enter a value: yes
oci_identity_compartment.WildTestCompartment: Creating...
oci_identity_compartment.WildTestCompartment: Creation complete after 1s [id=ocid1.compartment.oc1..q]
oci_core_virtual_network.WildTestVCN: Creating...
oci_core_virtual_network.WildTestVCN: Creation complete after 1s [id=ocid1.vcn.oc1.eu-frankfurt-1.a]
oci_core_nat_gateway.WildTestNATGateway: Creating...
oci_core_dhcp_options.WildTestDHCPOptions: Creating...
oci_core_security_list.WildTestSecurityList: Creating...
oci_core_security_list.WildTestSecurityList: Creation complete after 0s [id=ocid1.securitylist.oc1.eu-frankfurt-1.a]
oci_core_dhcp_options.WildTestDHCPOptions: Creation complete after 0s [id=ocid1.dhcpoptions.oc1.eu-frankfurt-1.a]
oci_core_nat_gateway.WildTestNATGateway: Creation complete after 1s [id=ocid1.natgateway.oc1.eu-frankfurt-1.a]
oci_core_route_table.WildTestRouteTable: Creating...
oci_core_route_table.WildTestRouteTable: Creation complete after 1s [id=ocid1.routetable.oc1.eu-frankfurt-1.aa]
oci_core_subnet.WildTestSubnet: Creating...
oci_core_subnet.WildTestSubnet: Creation complete after 2s [id=ocid1.subnet.oc1.eu-frankfurt-1.q]
Check deployed Resources in OCI Cloud
Go to Menu > Networking > Virtual Cloud Networks

From List Scope, check if your new compartment WildTestCompartment has been created, and if so, select it:

Check if private subnet was created:

Check the Security Lists:

The Ingress Rules:

The Egress Rules:

And of course, check the NAT Gateway:

Destroying resources
For destroying resources, run the "terraform destroy" command:
root@deploymentmachine:/home/nat_example# terraform destroy
[ ... snip .... ]
Enter a value: yes
oci_core_subnet.WildTestSubnet: Destroying... [id=ocid1.subnet.oc1.eu-frankfurt-1.aaq]
oci_core_subnet.WildTestSubnet: Destruction complete after 1s
oci_core_route_table.WildTestRouteTable: Destroying... [id=ocid1.routetable.oc1.eu-frankfurt-1.aa]
oci_core_dhcp_options.WildTestDHCPOptions: Destroying... [id=ocid1.dhcpoptions.oc1.eu-frankfurt-1.aa]
oci_core_security_list.WildTestSecurityList: Destroying... [id=ocid1.securitylist.oc1.eu-frankfurt-1.aa]
oci_core_security_list.WildTestSecurityList: Destruction complete after 0s
oci_core_dhcp_options.WildTestDHCPOptions: Destruction complete after 0s
oci_core_route_table.WildTestRouteTable: Destruction complete after 0s
oci_core_nat_gateway.WildTestNATGateway: Destroying... [id=ocid1.natgateway.oc1.eu-frankfurt-1.aaaa5a]
oci_core_nat_gateway.WildTestNATGateway: Destruction complete after 1s
oci_core_virtual_network.WildTestVCN: Destroying... [id=ocid1.vcn.oc1.eu-frankfurt-1.a5a]
oci_core_virtual_network.WildTestVCN: Destruction complete after 1s
oci_identity_compartment.WildTestCompartment: Destroying... [id=ocid1.compartment.oc1..aaq]
oci_identity_compartment.WildTestCompartment: Destruction complete after 0s
Last updated