Freestyle Docs

Freestyle / Docs

VPCs

Create private networks and attach Freestyle VMs to them.

VPCs let Freestyle VMs communicate over private addresses. Use them for databases, internal services, worker pools, or any group of VMs that should not depend on public domains.

Freestyle VPCs are dual-stack. Every VPC gets an IPv6 /64 and an IPv4 /24, and members take an address from each — so a service that binds 0.0.0.0, or a container on a v4-only bridge, is reachable from the rest of the network without anyone configuring anything.

Create A VPC

import { Freestyle } from "freestyle";

const freestyle = new Freestyle();
const { vpc, vpcId, data } = await freestyle.vpc.create({
  slug: "workspace-network",
  cidr: "10.40.0.0/24",
  // Membership is not permission: without this rule, members of the network
  // do not reach each other at all. See the firewall page.
  firewall: { rules: [{ action: "allow", source: {}, destination: {} }] },
});

console.log(vpcId, data.cidr, data.cidrV6);

Both CIDRs are optional: omit cidr and Freestyle derives a /24 out of 10.0.0.0/8, omit cidrV6 and it derives a unique-local /64. Name cidr yourself when the network has to reach an existing estate over a tunnel and must not overlap it, or when it needs more than 254 IPv4 members.

The firewall block declares rules with the network, where a bare endpoint means the network being created — “members reach each other” is the rule nearly every network wants, and nothing on the network moves without it.

Attach VMs

A VM can join at most one VPC. Declare the attachment when the VM is created — pass the VPC ID or your slug for it — or change it later with the update-networks API (PUT /v5/vms/{vmIdOrSlug}/networks), which attaches, re-addresses, or detaches declaratively whether the VM is stopped, running, or paused:

const { vm: apiVm } = await freestyle.vms.create({
  // Required: a VM reaches nothing it has not been allowed to.
  firewall: { rules: [{ action: "allow", source: {}, destination: { public: true } }] },
  slug: "api",
  networks: [{ vpc: vpcId, ipv4: "10.40.0.10" }],
});

const { vm: workerVm, data: worker } = await freestyle.vms.create({
  // Required: a VM reaches nothing it has not been allowed to.
  firewall: { rules: [{ action: "allow", source: {}, destination: { public: true } }] },
  slug: "worker",
  networks: [{ vpc: vpcId, ipv4: true }],
});

console.log(worker.networks[0]?.ipv4, worker.networks[0]?.ipv6);

Both families are allocated by default, so ipv4/ipv6 only matter when you want to pin an address or opt out. Pass a string to pin one, true to allocate explicitly, or false to make the member single-family.

Install an in-guest static route when another VPC member is acting as a router:

const { vm } = await freestyle.vms.create({
  // Required: a VM reaches nothing it has not been allowed to.
  firewall: { rules: [{ action: "allow", source: {}, destination: { public: true } }] },
  networks: [{
    vpc: vpcId,
    ipv4: "10.40.0.20",
    routes: [{ cidr: "172.20.0.0/16", via: "10.40.0.1" }],
  }],
});

Test Private Connectivity

Bind destination services to 0.0.0.0 for IPv4, or :: for both address families, then connect using the address in VmData.networksworker was allocated its address rather than pinning one, so read it back rather than guessing it:

const workerIp = worker.networks[0]?.ipv4;
await workerVm.exec("nohup python3 -m http.server 8080 --bind 0.0.0.0 >/tmp/http.log 2>&1 &");
const result = await apiVm.exec(`curl http://${workerIp}:8080`);
console.log(result.stdout);

This works because the network was created with the members-reach-each-other rule above; without it, the curl would time out.

Connect From Your Computer

Create a persistent WireGuard peer with tunnels, then use the returned config whenever your computer needs access to the VPC.

Manage VPCs

const { vpcs } = await freestyle.vpc.list();
const current = await freestyle.vpc.get("workspace-network");
await vpc.update({ slug: "private-workers" });
await vpc.delete();

Delete or move every attached VM, and detach every tunnel, before deleting a VPC.

esc