Skip to content

Internet access

Draft — pilot feature

Private Networks is in a limited pilot and this page is a work in progress.

An instance with only a private IP has no internet access in either direction: it cannot be reached from the internet, and it cannot reach the internet.

There are three ways to change that:

Option 1. Give the instance a public IP

The simplest option. Choose Public + Private IP at deploy time. The instance gets a public IPv4 1:1-NAT'd to its private address, with both inbound and outbound internet access. Verda does not filter inbound traffic, so run a guest firewall such as ufw or nftables on the instance, see Securing your instance.

Option 2. Jump host

Deploy one instance with a public IP and keep every other instance private. The public one acts as a bastion: you SSH to it, and from there to the private instances over their private addresses.

# One hop, using the jump host as a proxy
ssh -J root@<jump-host-public-ip> [email protected]

This gives you access, not egress, the private instances still have no outbound internet.

Option 3. Route the subnet's egress through a NAT instance

To give private instances outbound internet, add a route on the subnet that sends 0.0.0.0/0 through one of the network's instances.

Requirements for the target instance:

  • it must be on the same private network;
  • it must have a public IP.

You are responsible for configuring forwarding and NAT on that instance. It is an ordinary instance you own, billed as one, and it is a single point of failure for the subnet's egress.

Guest-side configuration

SSH into the instance you pointed the route at, and paste the following.

This script removes ufw

It installs iptables-persistent, which conflicts with ufw on Ubuntu. If ufw status reports Status: active, recreate your inbound rules with iptables after running the script and save them with netfilter-persistent save.

cat > setup-gateway <<'GWEOF'
#!/usr/bin/env bash

set -euo pipefail

IFACE=$(ip -o -4 route show to default | awk '{print $5; exit}')

cat > /etc/sysctl.d/99-nat-gateway.conf <<EOF
net.ipv4.ip_forward = 1
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.default.send_redirects = 0
# The kernel ORs the per-interface value with the ones above, so clear it too,
# or the gateway ICMP-redirects clients to a next hop that will not NAT them.
net.ipv4.conf.$IFACE.send_redirects = 0
EOF
sysctl --system >/dev/null

iptables -t nat -A POSTROUTING -o "$IFACE" -j MASQUERADE

# Docker sets the FORWARD policy to DROP and leaves DOCKER-USER for our rules.
iptables -nL DOCKER-USER >/dev/null 2>&1 \
    && iptables -I DOCKER-USER -i "$IFACE" -o "$IFACE" -j ACCEPT \
    || iptables -A FORWARD -i "$IFACE" -o "$IFACE" -j ACCEPT

apt-get update -qq
DEBIAN_FRONTEND=noninteractive apt-get install -y -qq iptables-persistent
netfilter-persistent save

echo "NAT gateway ready on $IFACE"
GWEOF

chmod +x setup-gateway
./setup-gateway

Verify from a private instance:

curl -s https://ifconfig.me    # should print the gateway's public IP

Managed internet gateway (coming soon)

The Enable internet gateway toggle in the subnet dialog is not yet functional. When it's available, it will give the subnet shared outbound internet through a Verda-managed gateway.