Project networking setup
The canonical NimbusNexus network setup for a multi-tier application: a private network with two subnets (public-facing and database-only), a router connecting the public subnet to the internet, and security groups restricting traffic between tiers. This guide walks the setup end-to-end and explains why each piece exists.
By the end you'll have:
- A network with two subnets (
10.0.1.0/24for web,10.0.2.0/24for database) - A router with an external gateway, attached to the web subnet
- Two security groups:
web-sg(HTTPS open to internet) anddb-sg(port 5432 only fromweb-sg) - A test pattern for verifying isolation works
Why this layout
Single-VM apps don't need any of this — a VM with a floating IP and no network configuration works fine. This layout is for apps that:
- Have multiple components (web tier + database, web tier + worker tier + cache, ...)
- Need to keep parts of the stack off the public internet
- Want to enforce "the web tier can talk to the DB tier; nothing else can"
For a true single-VM application, see Container deployment patterns instead.
Prereqs
- API key with
networks:writeandvms:writescopes. - A region picked (we'll use
us-east-1). - A rough idea of which VMs / services you want in which tier.
export NIMBUS_KEY="nn_live_xxxxxxxxxxxxxxxx"
export REGION="us-east-1"
1 · Create the network
A network is the L2 broadcast domain — every VM and resource attached to the same network can route to each other (subject to security groups).
curl -X POST https://api.nimbusnexus.net/v1/networks \
-H "Authorization: Bearer $NIMBUS_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "app-network",
"region": "us-east-1",
"cidr": "10.0.0.0/16"
}'
The 10.0.0.0/16 block is the address space for everything inside this network. Pick something that doesn't overlap with your office VPN, your home network, or any other network you might peer with later (so 192.168.0.0/16 is usually a poor choice — too commonly used). 10.0.0.0/16 works for most setups; 172.16.0.0/12 is fine too.
Save the network ID:
export NET_ID="net_01HG7Y3..."
2 · Create two subnets
Carve the network into two subnets — one for things that face the public internet, one for things that shouldn't.
# Web subnet — VMs that need internet access
curl -X POST https://api.nimbusnexus.net/v1/subnets \
-H "Authorization: Bearer $NIMBUS_KEY" \
-H "Content-Type: application/json" \
-d "{
\"name\": \"web\",
\"network_id\": \"$NET_ID\",
\"cidr\": \"10.0.1.0/24\",
\"gateway_ip\": \"10.0.1.1\"
}"
# Database subnet — for tier-2 resources
curl -X POST https://api.nimbusnexus.net/v1/subnets \
-H "Authorization: Bearer $NIMBUS_KEY" \
-H "Content-Type: application/json" \
-d "{
\"name\": \"db\",
\"network_id\": \"$NET_ID\",
\"cidr\": \"10.0.2.0/24\",
\"gateway_ip\": \"10.0.2.1\"
}"
The gateway IP is the address of the router's interface on that subnet. VMs use it as their default route.
3 · Create the router and attach it to the web subnet
The router is what gets traffic from the web subnet out to the internet (and back). The database subnet doesn't get a router connection — that's how you keep it off the public internet.
curl -X POST https://api.nimbusnexus.net/v1/routers \
-H "Authorization: Bearer $NIMBUS_KEY" \
-H "Content-Type: application/json" \
-d "{
\"name\": \"app-router\",
\"region\": \"us-east-1\",
\"external_gateway\": true
}"
external_gateway: true allocates a public IP on the router and enables SNAT for outbound traffic from subnets attached to it.
Save the router ID and attach it to the web subnet:
export ROUTER_ID="rtr_01HG7Y3..."
curl -X POST https://api.nimbusnexus.net/v1/routers/$ROUTER_ID/interfaces \
-H "Authorization: Bearer $NIMBUS_KEY" \
-H "Content-Type: application/json" \
-d "{ \"subnet_id\": \"$WEB_SUBNET_ID\" }"
The DB subnet stays off the router. Anything in the DB subnet can only reach what's reachable via the L2 network — which means other things in the same network, controlled by security groups.
4 · Create the security groups
Security groups are stateful firewalls applied to a VM's network interfaces. They control what traffic gets in (ingress) and what goes out (egress). "Stateful" means a connection initiated from inside is automatically allowed back — you only need rules for connections initiated from outside.
# Web security group — HTTPS open to the internet
curl -X POST https://api.nimbusnexus.net/v1/security-groups \
-H "Authorization: Bearer $NIMBUS_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "web-sg",
"region": "us-east-1",
"ingress_rules": [
{ "protocol": "tcp", "port": 443, "source_cidr": "0.0.0.0/0", "description": "HTTPS" },
{ "protocol": "tcp", "port": 22, "source_cidr": "203.0.113.5/32", "description": "SSH from office" }
],
"egress_rules": [
{ "protocol": "any", "destination_cidr": "0.0.0.0/0", "description": "anywhere" }
]
}'
# DB security group — port 5432 only from the web SG
curl -X POST https://api.nimbusnexus.net/v1/security-groups \
-H "Authorization: Bearer $NIMBUS_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "db-sg",
"region": "us-east-1",
"ingress_rules": [
{ "protocol": "tcp", "port": 5432, "source_security_group": "web-sg", "description": "Postgres from web tier" }
],
"egress_rules": [
{ "protocol": "any", "destination_cidr": "0.0.0.0/0", "description": "anywhere" }
]
}'
The source_security_group in the DB SG's rule is what enforces "only the web tier can connect" — instead of a static CIDR, the rule references the SG itself. Any VM tagged with web-sg can reach the DB. Add or remove VMs from web-sg and the access list updates automatically.
The web SG opens port 22 (SSH) from a specific office IP, not the world. Don't open SSH to 0.0.0.0/0 — every cloud has scanners checking 22 for weak passwords.
5 · Attach VMs
When creating a VM, specify the network, subnet, and security groups:
# Web tier VM
curl -X POST https://api.nimbusnexus.net/v1/vms \
-H "Authorization: Bearer $NIMBUS_KEY" \
-H "Content-Type: application/json" \
-d "{
\"name\": \"web-01\",
\"size\": \"gp-2-4\",
\"region\": \"us-east-1\",
\"image\": \"ubuntu-24.04\",
\"network_interfaces\": [
{ \"subnet_id\": \"$WEB_SUBNET_ID\", \"security_groups\": [\"web-sg\"] }
]
}"
# Database tier VM (if running DB on your own VM rather than managed DB)
curl -X POST https://api.nimbusnexus.net/v1/vms \
-H "Authorization: Bearer $NIMBUS_KEY" \
-H "Content-Type: application/json" \
-d "{
\"name\": \"db-01\",
\"size\": \"gp-4-8\",
\"region\": \"us-east-1\",
\"image\": \"ubuntu-24.04\",
\"network_interfaces\": [
{ \"subnet_id\": \"$DB_SUBNET_ID\", \"security_groups\": [\"db-sg\"] }
]
}"
For external access to the web VM, allocate a floating IP and attach it. The DB VM never gets a floating IP — that's how the network isolation works.
6 · Verify isolation
Test that the design actually enforces what you wanted:
# From the web VM, can we reach the DB on 5432? (Should: yes)
nc -v -w 3 10.0.2.10 5432
# From the web VM, can we reach the DB on 22 (SSH)? (Should: no — DB SG only opens 5432)
nc -v -w 3 10.0.2.10 22
# From your laptop, can we reach the DB directly? (Should: no — DB subnet isn't routable from internet)
nc -v -w 3 <DB_PUBLIC_IP> 5432 # there's no public IP, this fails
If any of these don't behave as expected, the security group rules or the network/subnet attachments are off. Re-check.
What this isn't
- Not VPC peering. This is one project's internal network. Two NimbusNexus projects' networks don't peer — by design (see Security model).
- Not a complete WAF or DDoS layer. Security groups are L3/L4 — they can't inspect HTTP request bodies. For application-layer filtering, run a WAF (e.g. ModSecurity behind nginx) in the web tier.
- Not autoscaling. You're managing the VMs manually. For autoscaled fleets, the same network primitives work, but you'd want infrastructure-as-code (Terraform, Pulumi) to manage them at scale.
Next steps
- Networks reference — every option for the create call.
- Subnets reference — IPv6 setup, DHCP options, DNS nameserver overrides.
- Security groups reference — the full rule syntax.
- Routers reference — static routes, BGP advertisement, more advanced wiring.
- Floating IPs — the public-IP primitive that ties this to the outside world.