@peerbit/server 6.0.41 → 7.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/src/cli.d.ts.map +1 -1
- package/dist/src/cli.js +161 -352
- package/dist/src/cli.js.map +1 -1
- package/dist/src/client.d.ts +1 -1
- package/dist/src/client.d.ts.map +1 -1
- package/dist/src/client.js +2 -5
- package/dist/src/client.js.map +1 -1
- package/dist/src/docker.d.ts +70 -1
- package/dist/src/docker.d.ts.map +1 -1
- package/dist/src/docker.js +559 -14
- package/dist/src/docker.js.map +1 -1
- package/dist/src/domain-lease.d.ts +126 -0
- package/dist/src/domain-lease.d.ts.map +1 -0
- package/dist/src/domain-lease.js +800 -0
- package/dist/src/domain-lease.js.map +1 -0
- package/dist/src/domain.d.ts +50 -2
- package/dist/src/domain.d.ts.map +1 -1
- package/dist/src/domain.js +484 -67
- package/dist/src/domain.js.map +1 -1
- package/dist/src/hetzner.d.ts +4 -21
- package/dist/src/hetzner.d.ts.map +1 -1
- package/dist/src/hetzner.js +4 -116
- package/dist/src/hetzner.js.map +1 -1
- package/dist/src/nginx-template.conf +19 -1
- package/dist/src/remotes.browser.d.ts +4 -1
- package/dist/src/remotes.browser.d.ts.map +1 -1
- package/dist/src/remotes.browser.js +1 -2
- package/dist/src/remotes.browser.js.map +1 -1
- package/dist/src/remotes.d.ts +2 -1
- package/dist/src/remotes.d.ts.map +1 -1
- package/dist/src/remotes.js +1 -0
- package/dist/src/remotes.js.map +1 -1
- package/dist/src/server.d.ts.map +1 -1
- package/dist/src/server.js +3 -5
- package/dist/src/server.js.map +1 -1
- package/dist/test/api.spec.js +2 -1
- package/dist/test/api.spec.js.map +1 -1
- package/dist/test/cli.spec.js +48 -1
- package/dist/test/cli.spec.js.map +1 -1
- package/dist/test/docker.spec.d.ts +2 -0
- package/dist/test/docker.spec.d.ts.map +1 -0
- package/dist/test/docker.spec.js +822 -0
- package/dist/test/docker.spec.js.map +1 -0
- package/dist/test/domain-lease.spec.d.ts +2 -0
- package/dist/test/domain-lease.spec.d.ts.map +1 -0
- package/dist/test/domain-lease.spec.js +530 -0
- package/dist/test/domain-lease.spec.js.map +1 -0
- package/dist/test/domain.integration.spec.js +358 -75
- package/dist/test/domain.integration.spec.js.map +1 -1
- package/dist/test/remotes.spec.d.ts +2 -0
- package/dist/test/remotes.spec.d.ts.map +1 -0
- package/dist/test/remotes.spec.js +15 -0
- package/dist/test/remotes.spec.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/ui/assets/index-CjZwCewh.js +10 -0
- package/dist/ui/assets/index-e3g42MbC.js +9 -0
- package/dist/ui/index.html +1 -1
- package/package.json +14 -19
- package/src/cli.ts +204 -408
- package/src/client.ts +2 -6
- package/src/docker.ts +841 -20
- package/src/domain-lease.ts +1118 -0
- package/src/domain.ts +650 -90
- package/src/hetzner.ts +4 -184
- package/src/nginx-template.conf +19 -1
- package/src/remotes.browser.ts +7 -1
- package/src/remotes.ts +6 -1
- package/src/server.ts +3 -5
- package/dist/src/aws.browser.d.ts +0 -2
- package/dist/src/aws.browser.d.ts.map +0 -1
- package/dist/src/aws.browser.js +0 -3
- package/dist/src/aws.browser.js.map +0 -1
- package/dist/src/aws.d.ts +0 -30
- package/dist/src/aws.d.ts.map +0 -1
- package/dist/src/aws.js +0 -240
- package/dist/src/aws.js.map +0 -1
- package/dist/test/launch.spec.d.ts +0 -2
- package/dist/test/launch.spec.d.ts.map +0 -1
- package/dist/test/launch.spec.js +0 -23
- package/dist/test/launch.spec.js.map +0 -1
- package/dist/ui/assets/index-BBTKOM0z.js +0 -6
- package/dist/ui/assets/index-DVtj_GOf.js +0 -13
- package/src/aws.browser.ts +0 -1
- package/src/aws.ts +0 -327
package/src/aws.browser.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
// Unsupported
|
package/src/aws.ts
DELETED
|
@@ -1,327 +0,0 @@
|
|
|
1
|
-
/* eslint-disable no-console */
|
|
2
|
-
/* eslint-disable @typescript-eslint/naming-convention */
|
|
3
|
-
import { type PeerId } from "@libp2p/interface";
|
|
4
|
-
import { delay } from "@peerbit/time";
|
|
5
|
-
|
|
6
|
-
export const createRecord = async (options: {
|
|
7
|
-
domain: string;
|
|
8
|
-
region?: string;
|
|
9
|
-
hostedZoneId: string;
|
|
10
|
-
credentials?: { accessKeyId: string; secretAccessKey: string };
|
|
11
|
-
}): Promise<void> => {
|
|
12
|
-
const { Route53Client, ChangeResourceRecordSetsCommand } = await import(
|
|
13
|
-
"@aws-sdk/client-route-53"
|
|
14
|
-
);
|
|
15
|
-
const { isIPv4, isIPv6 } = await import("net");
|
|
16
|
-
const { getMyIp } = await import("./domain.js");
|
|
17
|
-
|
|
18
|
-
const myIp = await getMyIp();
|
|
19
|
-
const v4 = isIPv4(myIp);
|
|
20
|
-
const v6 = isIPv6(myIp);
|
|
21
|
-
|
|
22
|
-
if (!v6 && !v4) {
|
|
23
|
-
throw new Error("Unknown ip type");
|
|
24
|
-
}
|
|
25
|
-
// TODO, make sure it works for ipv6 addresses with leading and trailing colon
|
|
26
|
-
const client = new Route53Client({
|
|
27
|
-
region: options.region,
|
|
28
|
-
credentials: options.credentials
|
|
29
|
-
? {
|
|
30
|
-
accessKeyId: options.credentials.accessKeyId,
|
|
31
|
-
secretAccessKey: options.credentials.secretAccessKey,
|
|
32
|
-
}
|
|
33
|
-
: undefined,
|
|
34
|
-
});
|
|
35
|
-
const cmd = new ChangeResourceRecordSetsCommand({
|
|
36
|
-
ChangeBatch: {
|
|
37
|
-
Changes: [
|
|
38
|
-
{
|
|
39
|
-
Action: "CREATE",
|
|
40
|
-
ResourceRecordSet: {
|
|
41
|
-
Name: options.domain,
|
|
42
|
-
Type: v4 ? "A" : "AAAA",
|
|
43
|
-
TTL: 60,
|
|
44
|
-
ResourceRecords: [{ Value: myIp }],
|
|
45
|
-
},
|
|
46
|
-
},
|
|
47
|
-
],
|
|
48
|
-
},
|
|
49
|
-
HostedZoneId: options.hostedZoneId,
|
|
50
|
-
});
|
|
51
|
-
await client.send(cmd);
|
|
52
|
-
};
|
|
53
|
-
|
|
54
|
-
const setupUserData = (
|
|
55
|
-
email: string,
|
|
56
|
-
grantAccess: PeerId[] = [],
|
|
57
|
-
serverVersion?: string,
|
|
58
|
-
) => {
|
|
59
|
-
const peerIdStrings = grantAccess.map((x) => x.toString());
|
|
60
|
-
const grantArgs = peerIdStrings.map((key) => `--ga ${key}`).join(" ");
|
|
61
|
-
|
|
62
|
-
// better-sqlite3 force use to install build-essentials for `make` command, TOOD dont bundle better-sqlite3 by default?
|
|
63
|
-
const versionSpec = serverVersion ? `@${serverVersion}` : "";
|
|
64
|
-
return `#!/bin/bash
|
|
65
|
-
cd /home/ubuntu
|
|
66
|
-
curl -fsSL https://deb.nodesource.com/setup_22.x | sudo -E bash - &&\
|
|
67
|
-
sudo apt-get install -y nodejs
|
|
68
|
-
sudo apt-get install -y build-essential
|
|
69
|
-
npm install -g @peerbit/server${versionSpec}
|
|
70
|
-
sudo peerbit domain test --email ${email}
|
|
71
|
-
peerbit start ${grantArgs} > log.txt 2>&1 &
|
|
72
|
-
`;
|
|
73
|
-
};
|
|
74
|
-
const PURPOSE_TAG_NAME = "Purpose";
|
|
75
|
-
const PURPOSE_TAG_VALUE = "Peerbit";
|
|
76
|
-
|
|
77
|
-
// Ubuntu Server 20.04 LTS (HVM), SSD Volume Type (64-bit (Arm))
|
|
78
|
-
export const AWS_LINUX_ARM_AMIs: Record<string, string> = {
|
|
79
|
-
/* "af-south-1" */
|
|
80
|
-
"ap-northeast-1": "ami-01444f83954203c6f",
|
|
81
|
-
"ap-northeast-2": "ami-0ac62099928d25fec",
|
|
82
|
-
"ap-northeast-3": "ami-0efdceaebc778c5f3",
|
|
83
|
-
"ap-south-1": "ami-0df6182e39efe7c4d",
|
|
84
|
-
"ap-southeast-1": "ami-01d87e25d3c65ec37",
|
|
85
|
-
"ap-southeast-2": "ami-0641fc20c25fdd380",
|
|
86
|
-
/* "ap-south-2", */
|
|
87
|
-
/* "ap-southeast-3",
|
|
88
|
-
"ap-southeast-4", */
|
|
89
|
-
"ca-central-1": "ami-0a3e942fe4813672b",
|
|
90
|
-
/* "cn-north-1",
|
|
91
|
-
"cn-northwest-1", */
|
|
92
|
-
"eu-central-1": "ami-0d85ad3aa712d96af",
|
|
93
|
-
/* "eu-central-2", */
|
|
94
|
-
"eu-north-1": "ami-0ff124a3d7381bfec",
|
|
95
|
-
/* "eu-south-1",
|
|
96
|
-
"eu-south-2", */
|
|
97
|
-
"eu-west-1": "ami-09c59b011574e4c96",
|
|
98
|
-
"eu-west-2": "ami-03e26d11b665ac7be",
|
|
99
|
-
"eu-west-3": "ami-00771c0ac817397bd",
|
|
100
|
-
/* "il-central-1",
|
|
101
|
-
"me-central-1",
|
|
102
|
-
"me-south-1", */
|
|
103
|
-
"sa-east-1": "ami-08dc4b989f93eafb9",
|
|
104
|
-
"us-east-1": "ami-097d5b19d4f1a7d1b",
|
|
105
|
-
"us-east-2": "ami-0071e4b30f26879e2",
|
|
106
|
-
/* "us-gov-east-1",
|
|
107
|
-
"us-gov-west-1", */
|
|
108
|
-
"us-west-1": "ami-0dca369228f3b2ce7",
|
|
109
|
-
"us-west-2": "ami-0c79a55dda52434da",
|
|
110
|
-
};
|
|
111
|
-
export const launchNodes = async (properties: {
|
|
112
|
-
region?: string;
|
|
113
|
-
email: string;
|
|
114
|
-
count?: number;
|
|
115
|
-
size?: "micro" | "small" | "medium" | "large" | "xlarge" | "2xlarge";
|
|
116
|
-
namePrefix?: string;
|
|
117
|
-
grantAccess?: PeerId[];
|
|
118
|
-
serverVersion?: string;
|
|
119
|
-
}): Promise<
|
|
120
|
-
{ instanceId: string; publicIp: string; name: string; region: string }[]
|
|
121
|
-
> => {
|
|
122
|
-
if (properties.count && properties.count > 10) {
|
|
123
|
-
throw new Error(
|
|
124
|
-
"Unexpected node launch count: " +
|
|
125
|
-
properties.count +
|
|
126
|
-
". To prevent unwanted behaviour you can also launch 10 nodes at once",
|
|
127
|
-
);
|
|
128
|
-
}
|
|
129
|
-
const count = properties.count || 1;
|
|
130
|
-
|
|
131
|
-
const {
|
|
132
|
-
EC2Client,
|
|
133
|
-
CreateTagsCommand,
|
|
134
|
-
RunInstancesCommand,
|
|
135
|
-
DescribeSecurityGroupsCommand,
|
|
136
|
-
CreateSecurityGroupCommand,
|
|
137
|
-
AuthorizeSecurityGroupIngressCommand,
|
|
138
|
-
DescribeInstancesCommand,
|
|
139
|
-
} = await import("@aws-sdk/client-ec2");
|
|
140
|
-
const client = new EC2Client({ region: properties.region });
|
|
141
|
-
const regionString = await client.config.region();
|
|
142
|
-
|
|
143
|
-
let securityGroupOut = (
|
|
144
|
-
await client.send(
|
|
145
|
-
new DescribeSecurityGroupsCommand({
|
|
146
|
-
Filters: [
|
|
147
|
-
{ Name: "tag:" + PURPOSE_TAG_NAME, Values: [PURPOSE_TAG_VALUE] },
|
|
148
|
-
],
|
|
149
|
-
}),
|
|
150
|
-
)
|
|
151
|
-
)?.SecurityGroups?.[0];
|
|
152
|
-
if (!securityGroupOut) {
|
|
153
|
-
securityGroupOut = await client.send(
|
|
154
|
-
new CreateSecurityGroupCommand({
|
|
155
|
-
GroupName: "peerbit-node",
|
|
156
|
-
Description: "Security group for running Peerbit nodes",
|
|
157
|
-
}),
|
|
158
|
-
);
|
|
159
|
-
await client.send(
|
|
160
|
-
new CreateTagsCommand({
|
|
161
|
-
Resources: [securityGroupOut.GroupId!],
|
|
162
|
-
Tags: [{ Key: PURPOSE_TAG_NAME, Value: PURPOSE_TAG_VALUE }],
|
|
163
|
-
}),
|
|
164
|
-
);
|
|
165
|
-
await client.send(
|
|
166
|
-
new AuthorizeSecurityGroupIngressCommand({
|
|
167
|
-
GroupId: securityGroupOut.GroupId,
|
|
168
|
-
IpPermissions: [
|
|
169
|
-
{
|
|
170
|
-
IpRanges: [{ CidrIp: "0.0.0.0/0" }],
|
|
171
|
-
IpProtocol: "tcp",
|
|
172
|
-
FromPort: 80,
|
|
173
|
-
ToPort: 80,
|
|
174
|
-
}, // Frontend
|
|
175
|
-
{
|
|
176
|
-
IpRanges: [{ CidrIp: "0.0.0.0/0" }],
|
|
177
|
-
IpProtocol: "tcp",
|
|
178
|
-
FromPort: 443,
|
|
179
|
-
ToPort: 443,
|
|
180
|
-
}, // Frontend SSL
|
|
181
|
-
{
|
|
182
|
-
IpRanges: [{ CidrIp: "0.0.0.0/0" }],
|
|
183
|
-
IpProtocol: "tcp",
|
|
184
|
-
FromPort: 9002,
|
|
185
|
-
ToPort: 9002,
|
|
186
|
-
}, // HTTPS api
|
|
187
|
-
{
|
|
188
|
-
IpRanges: [{ CidrIp: "0.0.0.0/0" }],
|
|
189
|
-
IpProtocol: "tcp",
|
|
190
|
-
FromPort: 8082,
|
|
191
|
-
ToPort: 8082,
|
|
192
|
-
}, // HTTP api
|
|
193
|
-
{
|
|
194
|
-
IpRanges: [{ CidrIp: "0.0.0.0/0" }],
|
|
195
|
-
IpProtocol: "tcp",
|
|
196
|
-
FromPort: 4002,
|
|
197
|
-
ToPort: 4005,
|
|
198
|
-
}, // libp2p
|
|
199
|
-
{
|
|
200
|
-
IpRanges: [{ CidrIp: "0.0.0.0/0" }],
|
|
201
|
-
IpProtocol: "tcp",
|
|
202
|
-
FromPort: 22,
|
|
203
|
-
ToPort: 22,
|
|
204
|
-
}, // SSH
|
|
205
|
-
],
|
|
206
|
-
}),
|
|
207
|
-
);
|
|
208
|
-
}
|
|
209
|
-
const instanceTag =
|
|
210
|
-
"Peerbit" + (properties.namePrefix ? "-" + properties.namePrefix : "");
|
|
211
|
-
let existingCounter =
|
|
212
|
-
(
|
|
213
|
-
await client.send(
|
|
214
|
-
new DescribeInstancesCommand({
|
|
215
|
-
Filters: [{ Name: "tag:Purpose", Values: [instanceTag] }],
|
|
216
|
-
}),
|
|
217
|
-
)
|
|
218
|
-
).Reservations?.length || 0;
|
|
219
|
-
|
|
220
|
-
console.log("Region: " + regionString);
|
|
221
|
-
const instanceOut = await client.send(
|
|
222
|
-
new RunInstancesCommand({
|
|
223
|
-
ImageId: AWS_LINUX_ARM_AMIs[regionString],
|
|
224
|
-
SecurityGroupIds: [securityGroupOut.GroupId!],
|
|
225
|
-
InstanceType: ("t4g." + (properties.size || "micro")) as any, // TODO types
|
|
226
|
-
UserData: Buffer.from(
|
|
227
|
-
setupUserData(
|
|
228
|
-
properties.email,
|
|
229
|
-
properties.grantAccess,
|
|
230
|
-
properties.serverVersion,
|
|
231
|
-
),
|
|
232
|
-
).toString("base64"),
|
|
233
|
-
MinCount: count,
|
|
234
|
-
MaxCount: count,
|
|
235
|
-
// InstanceInitiatedShutdownBehavior: 'terminate' // to enable termination when node shutting itself down
|
|
236
|
-
}),
|
|
237
|
-
);
|
|
238
|
-
|
|
239
|
-
if (!instanceOut.Instances || instanceOut.Instances.length === 0) {
|
|
240
|
-
throw new Error("Failed to create instance");
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
const names: string[] = [];
|
|
244
|
-
for (const instance of instanceOut.Instances) {
|
|
245
|
-
existingCounter++;
|
|
246
|
-
const name =
|
|
247
|
-
(properties.namePrefix ? properties.namePrefix : "peerbit-node") +
|
|
248
|
-
"-" +
|
|
249
|
-
existingCounter;
|
|
250
|
-
names.push(name);
|
|
251
|
-
await client.send(
|
|
252
|
-
new CreateTagsCommand({
|
|
253
|
-
Resources: [instance.InstanceId!],
|
|
254
|
-
Tags: [
|
|
255
|
-
{ Key: "Name", Value: name },
|
|
256
|
-
{ Key: "Purpose", Value: instanceTag },
|
|
257
|
-
],
|
|
258
|
-
}),
|
|
259
|
-
);
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
// wait for AWS to recognize the new instance IDs and for public IPs to be assigned
|
|
263
|
-
const instanceIds = instanceOut.Instances.map((x) => x.InstanceId!);
|
|
264
|
-
const timeoutMs = 3 * 60 * 1000; // 3 minutes
|
|
265
|
-
const pollIntervalMs = 5000;
|
|
266
|
-
const start = Date.now();
|
|
267
|
-
let foundInstances: Array<{
|
|
268
|
-
InstanceId?: string;
|
|
269
|
-
PublicIpAddress?: string;
|
|
270
|
-
}> = [];
|
|
271
|
-
|
|
272
|
-
while (Date.now() - start < timeoutMs) {
|
|
273
|
-
try {
|
|
274
|
-
const info = await client.send(
|
|
275
|
-
new DescribeInstancesCommand({ InstanceIds: instanceIds }),
|
|
276
|
-
);
|
|
277
|
-
foundInstances =
|
|
278
|
-
info.Reservations?.flatMap((r) => r.Instances || []) || [];
|
|
279
|
-
const allPresent = foundInstances.length >= instanceIds.length;
|
|
280
|
-
const ips = new Map(
|
|
281
|
-
foundInstances
|
|
282
|
-
.filter((i) => i.InstanceId && i.PublicIpAddress)
|
|
283
|
-
.map((i) => [i.InstanceId!, i.PublicIpAddress!]),
|
|
284
|
-
);
|
|
285
|
-
const allHaveIp = instanceIds.every((id) => ips.has(id));
|
|
286
|
-
if (allPresent && allHaveIp) {
|
|
287
|
-
// reorder to original order
|
|
288
|
-
let publicIps = instanceIds.map((id) => ips.get(id)!);
|
|
289
|
-
if (publicIps.length > 0) {
|
|
290
|
-
// success
|
|
291
|
-
return publicIps.map((v, ix) => {
|
|
292
|
-
return {
|
|
293
|
-
instanceId: instanceOut.Instances![ix].InstanceId!,
|
|
294
|
-
publicIp: v,
|
|
295
|
-
name: names[ix],
|
|
296
|
-
region: regionString,
|
|
297
|
-
};
|
|
298
|
-
});
|
|
299
|
-
}
|
|
300
|
-
}
|
|
301
|
-
} catch (e: any) {
|
|
302
|
-
// AWS eventual consistency: sometimes returns InvalidInstanceID.NotFound immediately after RunInstances
|
|
303
|
-
const code = e?.Code || e?.name || e?.code;
|
|
304
|
-
if (code !== "InvalidInstanceID.NotFound") {
|
|
305
|
-
throw e;
|
|
306
|
-
}
|
|
307
|
-
}
|
|
308
|
-
await delay(pollIntervalMs);
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
throw new Error(
|
|
312
|
-
"Timed out waiting for instances to be describe-able with public IPs",
|
|
313
|
-
);
|
|
314
|
-
};
|
|
315
|
-
|
|
316
|
-
export const terminateNode = async (properties: {
|
|
317
|
-
instanceId: string;
|
|
318
|
-
region?: string;
|
|
319
|
-
}) => {
|
|
320
|
-
const { EC2Client, TerminateInstancesCommand } = await import(
|
|
321
|
-
"@aws-sdk/client-ec2"
|
|
322
|
-
);
|
|
323
|
-
const client = new EC2Client({ region: properties.region });
|
|
324
|
-
await client.send(
|
|
325
|
-
new TerminateInstancesCommand({ InstanceIds: [properties.instanceId] }),
|
|
326
|
-
);
|
|
327
|
-
};
|