Connecting two Raff VMs over a private VPC lets the servers communicate on private IPv4 addresses instead of exposing every service on public interfaces. A typical use case is a public application VM talking to a database, cache, worker, or internal API over the VPC while only the public edge accepts internet traffic.
This tutorial uses two Ubuntu 24.04 VMs in one Raff VPC. You will create or select a private CIDR, attach both VMs, identify the private interfaces without assuming they are named eth1, verify the Linux route that carries private traffic, allow only a temporary test flow through your firewalls, measure connectivity with iperf3, and then apply the same pattern to an application-to-database connection.
Raff's current VPC product page documents isolated layer-2 VPCs, managed NAT/DNS/DHCP, stateful security groups, RFC 1918 CIDRs from /16 through /28, and unmetered private traffic on a 25 Gbps internal network. Treat that 25 Gbps figure as the network-fabric specification, not a guaranteed per-VM iperf3 result: actual throughput depends on the VM, guest networking, protocol, CPU, and test method. Private-network isolation also does not mean application traffic is cryptographically encrypted, so continue using TLS or another secure protocol when your threat model requires encryption in transit.
Prerequisites:
- Two Raff VMs running Ubuntu 24.04 with SSH access
- A non-root sudo user on both VMs
- Access to Raff VPC/networking settings in the dashboard
- A planned RFC 1918 CIDR that does not conflict with networks you may later connect through VPN or peering
- UFW or another host firewall configured deliberately on both VMs
The examples use 10.20.0.10 for VM-A and 10.20.0.11 for VM-B. Replace them with the private addresses assigned to your VMs.
Step 1 — Choose a private CIDR before creating the VPC
Raff VPC currently accepts private IPv4 CIDRs from /16 through /28 and can suggest a /24 automatically. Use an RFC 1918 range and consider future networks before choosing it.
Common private address space includes:
10.0.0.0/8 172.16.0.0/12 192.168.0.0/16
For this tutorial, use an example network such as:
10.20.0.0/24
Do not automatically reuse the same CIDR as your office LAN, client VPN pool, another cloud VPC, or a network you expect to peer later. Overlap can make future routing and VPN design harder.
Verify: Record the CIDR you will use and confirm it does not overlap with any network that must later route to this VPC.
Step 2 — Create the Raff VPC
Open the VPC/networking section of the Raff dashboard and create a new VPC. Give it a descriptive name such as:
prod-app-vpc
Choose the CIDR from Step 1 or accept an appropriate auto-suggested range. Raff's current VPC model includes the managed gateway, DNS, and DHCP with the VPC, so attached VM interfaces can receive private addressing from the network.
The exact dashboard labels can evolve, but the workflow is the same: create a VPC, choose or accept the CIDR, then wait until the VPC reports that it is ready before attaching workloads.
Verify: The Raff dashboard should show the VPC as ready and display the expected CIDR, for example 10.20.0.0/24.
Step 3 — Attach VM-A and VM-B to the same VPC
Attach both VMs to the VPC from the Raff dashboard. The two VMs must belong to the same private network for the direct private-IP test in this tutorial.
Record the assigned private addresses. For example:
VM-A: 10.20.0.10 VM-B: 10.20.0.11
Do not assume the private Linux interface will be named eth1. Modern Ubuntu guests may use predictable names such as ens4, ens7, or another device name depending on how the NIC is presented.
If the dashboard exposes security groups for the VM or VPC, do not create a broad allow any from the entire VPC rule just for convenience. In later steps, permit only the temporary test flow or the actual service flow you need.
Verify: Both VM detail views should show attachment to the same VPC and a private IPv4 address from the VPC CIDR.
Step 4 — Identify the private interface and address on Ubuntu
SSH to VM-A and list interfaces in compact form:
ip -br addr
Then list IPv4 routes:
ip -4 route
Repeat on VM-B.
You are looking for the interface that owns each VM's VPC address. Example output might resemble:
ens3 UP 203.0.113.10/24 ens7 UP 10.20.0.10/24
On VM-B, the private interface may similarly own 10.20.0.11/24.
Do not create a Netplan file simply because an old tutorial expected eth1. First verify the actual device, dashboard attachment, DHCP state, and existing Netplan configuration. Writing a guessed interface name or route into Netplan can break remote networking.
Useful diagnostics are:
networkctl list sudo netplan status --all
Verify: Each VM should show one interface with its expected private VPC address, regardless of the interface's device name.
Step 5 — Verify that Linux routes peer traffic through the private NIC
From VM-A, ask the kernel how it would reach VM-B:
ip route get 10.20.0.11
Expected structure:
10.20.0.11 dev <private-interface> src 10.20.0.10
From VM-B, check the reverse path:
ip route get 10.20.0.10
This test is more useful than assuming that any successful request used the VPC. It tells you which interface and source IP Linux selected for that destination.
You can also inspect the neighbor table after traffic has been attempted:
ip neigh show
Verify: ip route get on each VM should select the private interface and the VM's private source IP for the peer's private address.
Step 6 — Allow only the temporary private-network test flow
For a deterministic connectivity test, use iperf3 on TCP port 5201. Install it on both VMs:
sudo apt update sudo apt install -y iperf3
On VM-B, allow only VM-A's private IP to reach the test port through UFW:
sudo ufw allow from 10.20.0.10 to any port 5201 proto tcp
If a Raff security group also filters private traffic, add an equivalent temporary inbound rule for TCP 5201 from 10.20.0.10/32 to VM-B. Keep the source specific rather than opening the port to the internet or the entire VPC without a reason.
Check the host rule:
sudo ufw status numbered
If UFW is currently inactive, do not enable it blindly on a remote server. Follow the Ubuntu 24.04 UFW tutorial so SSH access is allowed before the firewall is enabled.
Verify: VM-B should have a rule allowing TCP 5201 only from VM-A's private IP, and any Raff security-group rule should match the same intended source and destination.
Step 7 — Test private connectivity with ping and iperf3
A ping can provide a quick reachability signal when ICMP is allowed:
ping -c 4 10.20.0.11
Do not treat a failed ping as proof that the VPC is broken; ICMP may be blocked while TCP traffic is allowed.
For the application-layer test, start iperf3 on VM-B and bind it specifically to the private address:
iperf3 -s -B 10.20.0.11
From VM-A, connect to VM-B's private address:
iperf3 -c 10.20.0.11
The output reports measured throughput for this specific test. Do not compare it with a fixed expected number from an old benchmark. A result is affected by VM CPU, guest networking, TCP behavior, concurrent load, and the test duration.
While the test is active, you can confirm the connection endpoints on VM-B:
ss -tnp | grep ':5201'
Stop the iperf3 server with Ctrl+C when finished.
Verify: iperf3 should complete over 10.20.0.11, and the connection should use the private source/destination addresses rather than the VMs' public IPs.
Step 8 — Replace broad VPC access with service-specific rules
The production goal is not “all private VMs trust each other.” The goal is to allow the exact application relationship you need.
For example, if VM-A is an application server and VM-B runs PostgreSQL, allow only VM-A's private address to reach PostgreSQL on VM-B:
sudo ufw allow from 10.20.0.10 to any port 5432 proto tcp
If MySQL is the backend instead:
sudo ufw allow from 10.20.0.10 to any port 3306 proto tcp
Mirror that least-privilege rule in the Raff security group when a security group protects the VM.
Then configure the application to use the database's private address, for example:
DB_HOST=10.20.0.11 DB_PORT=5432
The database service itself should also bind only to the interfaces it actually needs. Do not make a database publicly reachable merely because its firewall currently blocks the port.
For PostgreSQL configuration and authentication, follow Install PostgreSQL on Ubuntu 24.04 rather than copying database settings from a networking tutorial.
Verify: The application VM should be able to reach the required service port over VM-B's private IP, while unrelated VPC sources should not gain access simply because they share the subnet.
Step 9 — Keep private-network isolation separate from encryption
Raff's current VPC documentation describes per-VPC layer-2 isolation and private addressing that is separated from other tenants and the public internet. That is a network isolation boundary.
It is not a replacement for protocol-level security. Private IP traffic is not automatically equivalent to a WireGuard tunnel or TLS session. For credentials, database sessions, administration, or sensitive service-to-service traffic, use the encryption and authentication controls appropriate to the protocol and threat model.
Examples include:
- PostgreSQL or MySQL TLS for database connections;
- HTTPS or mTLS for internal APIs where required;
- SSH for administrative access;
- WireGuard/IPsec when you need an encrypted tunnel between networks or endpoints.
For client-to-server private access, see Set Up WireGuard VPN on Ubuntu 24.04.
Verify: Document which private flows rely only on VPC isolation and which also require application-layer or tunnel encryption.
