How to Expose Inbound Services With NAT Gateway on Vultr

VPC only instances are isolated from the public internet and do not accept inbound connections by default. To expose specific services such as SSH or application endpoints, NAT Gateway port forwarding routes inbound traffic from the internet to selected services running on private instances inside a VPC.
This guide explains how to expose inbound services on VPC only instances with NAT Gateway port forwarding on Vultr.
Prerequisites
Before you begin, ensure you:
- Have access to the Vultr Customer Portal with permission to manage networking and compute resources.
- Have a Vultr API key with sufficient permissions.
- Have an existing VPC network with a NAT Gateway provisioned, and at least one VPC only instance deployed behind the NAT Gateway.
Identify Private IP Addresses of VPC Only Instances
Identify the private IP addresses of the VPC only instances running inside the VPC. These addresses are required when creating NAT Gateway port forwarding rules.
- Log in to the Vultr Customer Portal.
- Navigate to Products and click Network.
- Select VPC Networks.
- Choose the VPC associated with the NAT Gateway.
- Verify that all VPC only instances appear under Attached Nodes.
- Note the private IP address of the instance you want to access.
Create a NAT Gateway Port Forwarding Rule
Create a port forwarding rule on the NAT Gateway to expose a specific service running on a VPC only instance. The rule maps a public port on the NAT Gateway to a private IP address and port inside the VPC.
Export your Vultr API key as an environment variable.
console$ export VULTR_API_KEY=YOUR_VULTR_API_KEY
Replace
YOUR_VULTR_API_KEYwith your Vultr API key.List the VPC networks available in your account.
console$ curl -sS --location --request GET "https://api.vultr.com/v2/vpcs" \ --header "Content-Type: application/json" \ --header "Authorization: Bearer ${VULTR_API_KEY}" \ | jq .
Identify the ID of the VPC network that has the NAT Gateway provisioned.
Export the VPC ID as an environment variable.
console$ export VPC_ID=YOUR_VPC_ID
Replace
YOUR_VPC_IDwith the ID of your VPC network.Retrieve the NAT Gateway ID for the VPC.
console$ curl -sS --location "https://api.vultr.com/v2/vpcs/${VPC_ID}/nat-gateway" \ --header "Authorization: Bearer ${VULTR_API_KEY}" \ | jq .
From the output, copy the NAT Gateway ID for use in subsequent steps.
Export the NAT Gateway ID.
console$ export NAT_GATEWAY_ID=YOUR_NAT_GATEWAY_ID
Replace
YOUR_NAT_GATEWAY_IDwith your NAT Gateway ID.Create an SSH port forwarding rule to expose inbound access.
console$ curl -sS --location \ --request POST "https://api.vultr.com/v2/vpcs/${VPC_ID}/nat-gateway/${NAT_GATEWAY_ID}/global/port-forwarding-rules" \ --header "Content-Type: application/json" \ --header "Authorization: Bearer ${VULTR_API_KEY}" \ --data '{ "name": "ssh-to-private-instance", "protocol": "tcp", "external_port": 2222, "internal_ip": "PRIVATE_IP_OF_INSTANCE", "internal_port": 22, "enabled": true, "description": "SSH access to private instance" }' \ | jq .
Replace the following values as required:
- name: A descriptive unique name for the port forwarding rule.
- external_port: The public port exposed on the NAT Gateway.
- internal_ip: The private IP address of the instance in the VPC.
- internal_port: The port on which the service is listening on the instance.
- protocol: The transport protocol (
tcporudp).
Only the ports explicitly defined in port forwarding rules are accessible from the internet. All other inbound traffic to the private instance remains blocked. Repeat this step to create additional port forwarding rules for other instances or services by using their respective private IP addresses and ports.NoteVerify that the SSH port forwarding rule is active.
console$ curl -sS --location \ --request GET "https://api.vultr.com/v2/vpcs/${VPC_ID}/nat-gateway/${NAT_GATEWAY_ID}/global/port-forwarding-rules" \ --header "Authorization: Bearer ${VULTR_API_KEY}" \ | jq .
Verify that the rule appears in the output and that the enabled field is set to
true.
Verify Exposed SSH Access Through the NAT Gateway
After creating the port forwarding rule, verify that the NAT Gateway forwards inbound SSH traffic to the VPC only instance.
Identify the public IP address of the NAT Gateway.
console$ curl -sS --location "https://api.vultr.com/v2/vpcs/${VPC_ID}/nat-gateway" \ --header "Authorization: Bearer ${VULTR_API_KEY}" \ | jq '.nat_gateways[].public_ips[]'
The command returns the public IPv4 address assigned to the NAT Gateway.
Connect to the private instance over SSH using the NAT Gateway public IP and the forwarded port.
console$ ssh -p 2222 USERNAME@NAT_GATEWAY_PUBLIC_IP
Replace
USERNAMEwith the instance login user andNAT_GATEWAY_PUBLIC_IPwith the NAT Gateway public IP address.A successful login confirms that the NAT Gateway forwards inbound SSH traffic to the private instance correctly.
Verify Inter-instance Connectivity
VPC only instances connected to the same VPC network communicate with each other directly over private IP addresses without using the NAT Gateway.
Connect to one of the VPC only instances using the existing SSH port forwarding rule.
console$ ssh -p 2222 USERNAME@NAT_GATEWAY_PUBLIC_IP
From the connected instance, test connectivity to another VPC only instance using its private IP address.
console$ ping PRIVATE_IP_OF_OTHER_INSTANCE
Replace
PRIVATE_IP_OF_OTHER_INSTANCEwith the private IP address noted earlier.Successful responses confirm that the instances communicate internally within the VPC using private networking.
Deploy Demo Services and Expose Inbound Access Through the NAT Gateway
Deploy simple demo services on two VPC only instances and verify that they can access each other over private networking.
index.html file to demonstrate service communication inside a private VPC. In real-world scenarios, replace these steps with the deployment method required for your service, such as running containers with Docker, deploying a web framework, or starting application-specific services.
Deploy a Demo Service on Instance 1
Deploy a simple web service on Instance 1 to demonstrate an inbound service.
Connect to Instance 1 using the existing SSH port forwarding rule.
Install the Nginx web server.
console$ sudo apt update $ sudo apt install -y nginx
Create a demo page that identifies Instance 1.
console$ sudo tee /var/www/html/index.html > /dev/null <<EOF <h1>Demo Service - Instance 1</h1> <p>This service runs on Instance 1 inside the VPC.</p> EOF
Allow HTTP traffic through the firewall.
console$ sudo ufw allow 80
Verify that the service is running locally.
console$ curl http://localhost
A successful response confirms that the service is accessible.
Deploy a Demo Service on Instance 2
Deploy a simple web service on Instance 2 to demonstrate an inbound service.
Connect to Instance 2 using SSH, either through its own port forwarding rule or by initiating an SSH connection from Instance 1 using Instance 2’s private IP address.
Install the Nginx web server.
console$ sudo apt update $ sudo apt install -y nginx
Create a demo page that identifies Instance 2.
console$ sudo tee /var/www/html/index.html > /dev/null <<EOF <h1>Demo Service - Instance 2</h1> <p>This service runs on Instance 2 inside the VPC.</p> EOF
Allow HTTP traffic through the firewall.
console$ sudo ufw allow 80
Verify that the service is running locally.
console$ curl http://localhost
A successful response confirms that the service is accessible.
Verify Service Connectivity Between Instances
Verify that services on VPC only instances communicate with each other using private IP addresses.
From Instance 1, access the service running on Instance 2 using its private IP address.
console$ curl http://PRIVATE_IP_OF_INSTANCE_2
Replace
PRIVATE_IP_OF_INSTANCE_2with the private IP of Instance 2.From Instance 2, access the service running on Instance 1 using its private IP address.
console$ curl http://PRIVATE_IP_OF_INSTANCE_1
Replace
PRIVATE_IP_OF_INSTANCE_1with the private IP of Instance 1.
Expose the Service Through NAT Gateway
Expose the service running on Instance 1 by creating an HTTP port forwarding rule on the NAT Gateway. This maps a public port on the NAT Gateway to port 80 on the private instance.
Create an HTTP port forwarding rule.
console$ curl -sS --location \ --request POST "https://api.vultr.com/v2/vpcs/${VPC_ID}/nat-gateway/${NAT_GATEWAY_ID}/global/port-forwarding-rules" \ --header "Content-Type: application/json" \ --header "Authorization: Bearer ${VULTR_API_KEY}" \ --data '{ "name": "http-to-instance-1", "protocol": "tcp", "external_port": 8080, "internal_ip": "PRIVATE_IP_OF_INSTANCE_1", "internal_port": 80, "enabled": true, "description": "Expose HTTP service on Instance 1" }' \ | jq .
Replace
PRIVATE_IP_OF_INSTANCE_1with the private IP address of Instance 1.Verify that the HTTP port forwarding rule is active.
console$ curl -sS --location \ --request GET "https://api.vultr.com/v2/vpcs/${VPC_ID}/nat-gateway/${NAT_GATEWAY_ID}/global/port-forwarding-rules" \ --header "Authorization: Bearer ${VULTR_API_KEY}" \ | jq .
Confirm that the rule appears in the output and that the enabled field is set to
true.Access the service using the NAT Gateway public IP and exposed port.
console$ curl http://NAT_GATEWAY_PUBLIC_IP:8080
A successful response confirms that the service is exposed through the NAT Gateway and reachable from the public internet.
Conclusion
You have exposed inbound services on VPC only instances using a NAT Gateway on Vultr. By configuring port forwarding rules, you selectively publish services such as SSH and HTTP while keeping instances isolated from direct public access. Private instances continue to communicate internally over the VPC, and only explicitly defined ports become reachable from the internet.