info_tfgrid/collections/developers/javascript/grid3_wireguard_gateway.md
2024-05-06 10:34:37 -04:00

302 lines
8.7 KiB
Markdown

<h1> Deploying a VM with Wireguard and Gateway </h1>
<h2> Table of Contents </h2>
- [Introduction](#introduction)
- [Client Configurations](#client-configurations)
- [Code Example](#code-example)
- [Detailed Explanation](#detailed-explanation)
- [Get the Client](#get-the-client)
- [Get the Nodes](#get-the-nodes)
- [Deploy the VM](#deploy-the-vm)
- [Deploy the Gateway](#deploy-the-gateway)
- [Get the Deployments Information](#get-the-deployments-information)
- [Disconnect the Client](#disconnect-the-client)
- [Delete the Deployments](#delete-the-deployments)
- [Conclusion](#conclusion)
***
## Introduction
We present here the relevant information when it comes to deploying a virtual machine with Wireguard and a gateway.
## Client Configurations
To configure the client, have a look at [this section](./grid3_javascript_loadclient.md).
## Code Example
```ts
import { FilterOptions, GatewayNameModel, GridClient, MachineModel, MachinesModel, NetworkModel } from "../src";
import { config, getClient } from "./client_loader";
import { log } from "./utils";
function createNetworkModel(gwNode: number, name: string): NetworkModel {
return {
name,
addAccess: true,
accessNodeId: gwNode,
ip_range: "10.238.0.0/16",
} as NetworkModel;
}
function createMachineModel(node: number) {
return {
name: "testvm1",
node_id: node,
public_ip: false,
planetary: true,
cpu: 1,
memory: 1024 * 2,
rootfs_size: 0,
disks: [],
flist: "https://hub.grid.tf/tf-official-apps/threefoldtech-ubuntu-22.04.flist",
entrypoint: "/usr/bin/python3 -m http.server --bind ::",
env: {
SSH_KEY: config.ssh_key,
},
} as MachineModel;
}
function createMachinesModel(vm: MachineModel, network: NetworkModel): MachinesModel {
return {
name: "newVMs",
network,
machines: [vm],
metadata: "",
description: "test deploying VMs with wireguard via ts grid3 client",
} as MachinesModel;
}
function createGwModel(node_id: number, ip: string, networkName: string, name: string, port: number) {
return {
name,
node_id,
tls_passthrough: false,
backends: [`http://${ip}:${port}`],
network: networkName,
} as GatewayNameModel;
}
async function main() {
const grid3 = await getClient();
const gwNode = +(await grid3.capacity.filterNodes({ gateway: true }))[0].nodeId;
const vmQueryOptions: FilterOptions = {
cru: 1,
mru: 2, // GB
availableFor: grid3.twinId,
farmId: 1,
};
const vmNode = +(await grid3.capacity.filterNodes(vmQueryOptions))[0].nodeId;
const network = createNetworkModel(gwNode, "monNetwork");
const vm = createMachineModel(vmNode);
const machines = createMachinesModel(vm, network);
log(`Deploying vm on node: ${vmNode}, with network node: ${gwNode}`);
// deploy the vm
const vmResult = await grid3.machines.deploy(machines);
log(vmResult);
const deployedVm = await grid3.machines.getObj(machines.name);
log("+++ deployed vm +++");
log(deployedVm);
// deploy the gateway
const vmPrivateIP = (deployedVm as { interfaces: { ip: string }[] }[])[0].interfaces[0].ip;
const gateway = createGwModel(gwNode, vmPrivateIP, network.name, "pyserver", 8000);
log(`deploying gateway ${network.name} on node ${gwNode}`);
const gatewayResult = await grid3.gateway.deploy_name(gateway);
log(gatewayResult);
log("+++ Deployed gateway +++");
const deployedGw = await grid3.gateway.getObj(gateway.name);
log(deployedGw);
await grid3.disconnect();
}
main();
```
## Detailed Explanation
What we need to do with that code is: Deploy a name gateway with the wireguard IP as the backend; that allows accessing a server inside the vm through the gateway using the private network (wireguard) as the backend.
This will be done through the following steps:
### Get the Client
```ts
const grid3 = getClient();
```
### Get the Nodes
Determine the deploying nodes for the vm, network and gateway.
- Gateway and network access node
```ts
const gwNode = +(await grid3.capacity.filterNodes({ gateway: true }))[0].nodeId;
```
Using the `filterNodes` method, will get the first gateway node id, we will deploy the gateway and will use it as our network access node.
> The gateway node must be the same as the network access node.
- VM node
we need to set the filter options first for this example we will deploy the vm with 1 cpu, 2 GB of memory.
now will crete a `FilterOptions` object with that specs and get the firs node id of the result.
```ts
const vmQueryOptions: FilterOptions = {
cru: 1,
mru: 2, // GB
availableFor: grid3.twinId,
farmId: 1,
};
const vmNode = +(await grid3.capacity.filterNodes(vmQueryOptions))[0].nodeId;
```
### Deploy the VM
We need to create the network and machine models, the deploy the VM
```ts
const network = createNetworkModel(gwNode, "monNetwork");
const vm = createMachineModel(vmNode);
const machines = createMachinesModel(vm, network);
log(`Deploying vm on node: ${vmNode}, with network node: ${gwNode}`);
// deploy the vm
const vmResult = await grid3.machines.deploy(machines);
log(vmResult);
```
- `CreateNetWorkModel` :
we are creating a network and set the node id to be `gwNode`, the name `monNetwork` and inside the function we set `addAccess: true` to add __wireguard__ access.
- `createMachineModel` and `createMachinesModel` is similar to the previous section of [deploying a single VM](grid3_javascript_vm.md), but we are passing the created `NetworkModel` to the machines model and the entry point here runs a simple python server.
### Deploy the Gateway
Now we have our VM deployed with it's network, we need to make the gateway on the same node, same network and pointing to the VM's private IP address.
- Get the VM's private IP address:
```ts
const vmPrivateIP = (deployedVm as { interfaces: { ip: string }[] }[])[0].interfaces[0].ip;
```
- Create the Gateway name model:
```ts
const gateway = createGwModel(gwNode, vmPrivateIP, network.name, "pyserver", 8000);
```
This will create a `GatewayNameModel` with the following properties:
- `name` : the subdomain name
- `node_id` : the gateway node id
- `tls_passthrough: false`
- `backends: [`http://${ip}:${port}`]` : the private ip address and the port number of our machine
- `network: networkName` : the network name, we already created earlier.
### Get the Deployments Information
```ts
const deployedVm = await grid3.machines.getObj(machines.name);
log("+++ deployed vm +++");
log(deployedVm);
log("+++ Deployed gateway +++");
const deployedGw = await grid3.gateway.getObj(gateway.name);
log(deployedGw);
```
- `deployedVm` : is an array of one object contains the details about the vm deployment.
```ts
[
{
version: 0,
contractId: 30658,
nodeId: 11,
name: 'testvm1',
created: 1686225126,
status: 'ok',
message: '',
flist: 'https://hub.grid.tf/tf-official-apps/threefoldtech-ubuntu-22.04.flist',
publicIP: null,
planetary: '302:9e63:7d43:b742:3582:a831:cd41:3f19',
interfaces: [ { network: 'monNetwork', ip: '10.238.2.2' } ],
capacity: { cpu: 1, memory: 2048 },
mounts: [],
env: {
SSH_KEY: 'ssh'
},
entrypoint: '/usr/bin/python3 -m http.server --bind ::',
metadata: '{"type":"vm","name":"newVMs","projectName":""}',
description: 'test deploying VMs with wireguard via ts grid3 client',
rootfs_size: 0,
corex: false
}
]
```
- `deployedGw` : is an array of one object contains the details of the gateway name.
```ts
[
{
version: 0,
contractId: 30659,
name: 'pyserver1',
created: 1686225139,
status: 'ok',
message: '',
type: 'gateway-name-proxy',
domain: 'pyserver1.gent02.dev.grid.tf',
tls_passthrough: false,
backends: [ 'http://10.238.2.2:8000' ],
metadata: '{"type":"gateway","name":"pyserver1","projectName":""}',
description: ''
}
]
```
Now we can access the vm using the `domain` that returned in the object.
### Disconnect the Client
finally we need to disconnect the client using `await grid3.disconnect();`
### Delete the Deployments
If we want to delete the deployments we can just do this:
```ts
const deletedMachines = await grid3.machines.delete({ name: machines.name});
log(deletedMachines);
const deletedGW = await grid3.gateway.delete_name({ name: gateway.name});
log(deletedGW);
```
## Conclusion
This section presented a detailed description on how to create a virtual machine with private IP using Wireguard and use it as a backend for a name gateway.
If you have any questions, you can ask the ThreeFold community for help on the [ThreeFold Forum](http://forum.threefold.io/) or on the [ThreeFold Grid Tester Community](https://t.me/threefoldtesting) on Telegram.