pinokiod 3.8.22 → 3.8.24

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.
@@ -186,6 +186,7 @@ class Api {
186
186
  type: "disconnect"
187
187
  })
188
188
  console.timeEnd("stop 4")
189
+ await this.kernel.caddy.update()
189
190
  return true
190
191
  }
191
192
  async startScripts() {
@@ -1073,6 +1074,7 @@ class Api {
1073
1074
  })
1074
1075
  }
1075
1076
  }
1077
+ await this.kernel.caddy.update()
1076
1078
  } catch (e) {
1077
1079
  ondata({ raw: e.toString() })
1078
1080
  }
@@ -32,9 +32,6 @@ class Caddy {
32
32
  this.kernel.exec({
33
33
  message: `caddy run --watch`,
34
34
  path: this.kernel.homedir,
35
- kill: [{
36
- message: "caddy stop"
37
- }]
38
35
  }, (e) => {
39
36
  console.log("[CADDY] " + e.cleaned)
40
37
  if (!resolved) {
@@ -47,273 +44,274 @@ class Caddy {
47
44
  })
48
45
  })
49
46
  }
50
- const config = {
51
- "apps": {
52
- "http": {
53
- "servers": {
54
- "main": {
55
- "listen": ["127.0.0.1:443"],
56
- "routes": [
57
- {
58
- "match": [{ "method": ["OPTIONS"] }],
59
- "handle": [
60
- {
61
- "handler": "headers",
62
- "response": {
63
- "set": {
64
- "Access-Control-Allow-Origin": ["*"],
65
- "Access-Control-Allow-Methods": ["GET, POST, OPTIONS, PUT, DELETE"],
66
- "Access-Control-Allow-Headers": ["*"],
67
- "Vary": ["Origin"]
68
- }
69
- }
70
- },
71
- {
72
- "handler": "static_response",
73
- "status_code": 204
74
- }
75
- ]
76
- },
77
- {
78
- "match": [{ "host": ["pinokio.localhost"] }],
79
- "handle": [
80
- {
81
- "handler": "reverse_proxy",
82
- "upstreams": [{ "dial": "127.0.0.1:42000" }]
83
- },
84
- {
85
- "handler": "headers",
86
- "response": {
87
- "set": {
88
- "Access-Control-Allow-Origin": ["*"],
89
- "Access-Control-Allow-Methods": ["GET, POST, OPTIONS, PUT, DELETE"],
90
- "Access-Control-Allow-Headers": ["*"],
91
- "Vary": ["Origin"]
92
- }
93
- }
94
- }
95
- ]
96
- },
97
- {
98
- "match": [{ "host": ["l.pinokio.localhost"] }],
99
- "handle": [
100
- {
101
- "handler": "reverse_proxy",
102
- "upstreams": [{ "dial": "127.0.0.1:1234" }]
103
- },
104
- {
105
- "handler": "headers",
106
- "response": {
107
- "set": {
108
- "Access-Control-Allow-Origin": ["*"],
109
- "Access-Control-Allow-Methods": ["GET, POST, OPTIONS, PUT, DELETE"],
110
- "Access-Control-Allow-Headers": ["*"],
111
- "Vary": ["Origin"]
112
- }
113
- }
114
- }
115
- ]
116
- },
117
- {
118
- "match": [{ "host": ["o.pinokio.localhost"] }],
119
- "handle": [
120
- {
121
- "handler": "reverse_proxy",
122
- "upstreams": [{ "dial": "127.0.0.1:11434" }]
123
- },
124
- {
125
- "handler": "headers",
126
- "response": {
127
- "set": {
128
- "Access-Control-Allow-Origin": ["*"],
129
- "Access-Control-Allow-Methods": ["GET, POST, OPTIONS, PUT, DELETE"],
130
- "Access-Control-Allow-Headers": ["*"],
131
- "Vary": ["Origin"]
132
- }
133
- }
134
- }
135
- ]
136
- },
137
- {
138
- "match": [{ "host": ["a.pinokio.localhost"] }],
139
- "handle": [
140
- {
141
- "handler": "reverse_proxy",
142
- "upstreams": [{ "dial": "127.0.0.1:7860" }]
143
- },
144
- {
145
- "handler": "headers",
146
- "response": {
147
- "set": {
148
- "Access-Control-Allow-Origin": ["*"],
149
- "Access-Control-Allow-Methods": ["GET, POST, OPTIONS, PUT, DELETE"],
150
- "Access-Control-Allow-Headers": ["*"],
151
- "Vary": ["Origin"]
152
- }
153
- }
154
- }
155
- ]
156
- },
157
- {
158
- "match": [{ "host": ["b.pinokio.localhost"] }],
159
- "handle": [
160
- {
161
- "handler": "reverse_proxy",
162
- "upstreams": [{ "dial": "127.0.0.1:7861" }]
163
- },
164
- {
165
- "handler": "headers",
166
- "response": {
167
- "set": {
168
- "Access-Control-Allow-Origin": ["*"],
169
- "Access-Control-Allow-Methods": ["GET, POST, OPTIONS, PUT, DELETE"],
170
- "Access-Control-Allow-Headers": ["*"],
171
- "Vary": ["Origin"]
172
- }
173
- }
174
- }
175
- ]
176
- },
177
- {
178
- "match": [{ "host": ["c.pinokio.localhost"] }],
179
- "handle": [
180
- {
181
- "handler": "reverse_proxy",
182
- "upstreams": [{ "dial": "127.0.0.1:7862" }]
183
- },
184
- {
185
- "handler": "headers",
186
- "response": {
187
- "set": {
188
- "Access-Control-Allow-Origin": ["*"],
189
- "Access-Control-Allow-Methods": ["GET, POST, OPTIONS, PUT, DELETE"],
190
- "Access-Control-Allow-Headers": ["*"],
191
- "Vary": ["Origin"]
192
- }
193
- }
194
- }
195
- ]
196
- }
197
- ]
198
- }
199
- }
200
- }
201
- }
202
- }
203
-
204
- const config2 = {
205
- "apps": {
206
- "http": {
207
- "servers": {
208
- "main": {
209
- "listen": [":443"],
210
- //"listen": [":80"],
211
- "handle_response": [
212
- {
213
- "handler": "headers",
214
- "headers": {
215
- "Access-Control-Allow-Origin": ["*"],
216
- "Access-Control-Allow-Methods": ["GET", "POST", "OPTIONS", "PUT", "DELETE"],
217
- "Access-Control-Allow-Headers": ["*"]
218
- }
219
- }
220
- ],
221
- "routes": [
222
- {
223
- "match": [{ "method": ["OPTIONS"] }],
224
- "handle": [
225
- {
226
- "handler": "static_response",
227
- "headers": {
228
- "Access-Control-Allow-Origin": ["*"],
229
- "Access-Control-Allow-Methods": ["GET", "POST", "OPTIONS", "PUT", "DELETE"],
230
- "Access-Control-Allow-Headers": ["*"]
231
- },
232
- "status_code": 204
233
- }
234
- ]
235
- },
236
- {
237
- "match": [{ "host": ["pinokio.localhost"] }],
238
- "handle": [
239
- {
240
- "handler": "reverse_proxy",
241
- "upstreams": [{ "dial": "localhost:42000" }]
242
- }
243
- ]
244
- },
245
- {
246
- "match": [{ "host": ["l.pinokio.localhost"] }],
247
- "handle": [
248
- {
249
- "handler": "reverse_proxy",
250
- "upstreams": [{ "dial": "localhost:1234" }]
251
- }
252
- ]
253
- },
254
- {
255
- "match": [{ "host": ["a.pinokio.localhost"] }],
256
- "handle": [
257
- {
258
- "handler": "reverse_proxy",
259
- "upstreams": [{ "dial": "localhost:7860" }]
260
- }
261
- ]
262
- },
263
- {
264
- "match": [{ "host": ["b.pinokio.localhost"] }],
265
- "handle": [
266
- {
267
- "handler": "reverse_proxy",
268
- "upstreams": [{ "dial": "localhost:7861" }]
269
- }
270
- ]
271
- },
272
- {
273
- "match": [{ "host": ["c.pinokio.localhost"] }],
274
- "handle": [
275
- {
276
- "handler": "reverse_proxy",
277
- "upstreams": [{ "dial": "localhost:7862" }]
278
- }
279
- ]
280
- }
281
- ]
282
- }
283
- }
284
- },
285
- // "tls": {
286
- // "automation": {
287
- // "policies": [
288
- // {
289
- // "subjects": [
290
- // "pinokio.localhost",
291
- // "a.pinokio.localhost",
292
- // "b.pinokio.localhost",
293
- // "c.pinokio.localhost"
294
- // ],
295
- // "issuers": [
296
- // {
297
- // "module": "internal"
298
- // }
299
- // ]
300
- // }
301
- // ]
47
+ await this.kernel.caddy.update()
48
+ // const config = {
49
+ // "apps": {
50
+ // "http": {
51
+ // "servers": {
52
+ // "main": {
53
+ // "listen": ["127.0.0.1:443"],
54
+ // "routes": [
55
+ // {
56
+ // "match": [{ "method": ["OPTIONS"] }],
57
+ // "handle": [
58
+ // {
59
+ // "handler": "headers",
60
+ // "response": {
61
+ // "set": {
62
+ // "Access-Control-Allow-Origin": ["*"],
63
+ // "Access-Control-Allow-Methods": ["GET, POST, OPTIONS, PUT, DELETE"],
64
+ // "Access-Control-Allow-Headers": ["*"],
65
+ // "Vary": ["Origin"]
66
+ // }
67
+ // }
68
+ // },
69
+ // {
70
+ // "handler": "static_response",
71
+ // "status_code": 204
72
+ // }
73
+ // ]
74
+ // },
75
+ // {
76
+ // "match": [{ "host": ["pinokio.localhost"] }],
77
+ // "handle": [
78
+ // {
79
+ // "handler": "reverse_proxy",
80
+ // "upstreams": [{ "dial": "127.0.0.1:42000" }]
81
+ // },
82
+ // {
83
+ // "handler": "headers",
84
+ // "response": {
85
+ // "set": {
86
+ // "Access-Control-Allow-Origin": ["*"],
87
+ // "Access-Control-Allow-Methods": ["GET, POST, OPTIONS, PUT, DELETE"],
88
+ // "Access-Control-Allow-Headers": ["*"],
89
+ // "Vary": ["Origin"]
90
+ // }
91
+ // }
92
+ // }
93
+ // ]
94
+ // },
95
+ // {
96
+ // "match": [{ "host": ["l.pinokio.localhost"] }],
97
+ // "handle": [
98
+ // {
99
+ // "handler": "reverse_proxy",
100
+ // "upstreams": [{ "dial": "127.0.0.1:1234" }]
101
+ // },
102
+ // {
103
+ // "handler": "headers",
104
+ // "response": {
105
+ // "set": {
106
+ // "Access-Control-Allow-Origin": ["*"],
107
+ // "Access-Control-Allow-Methods": ["GET, POST, OPTIONS, PUT, DELETE"],
108
+ // "Access-Control-Allow-Headers": ["*"],
109
+ // "Vary": ["Origin"]
110
+ // }
111
+ // }
112
+ // }
113
+ // ]
114
+ // },
115
+ // {
116
+ // "match": [{ "host": ["o.pinokio.localhost"] }],
117
+ // "handle": [
118
+ // {
119
+ // "handler": "reverse_proxy",
120
+ // "upstreams": [{ "dial": "127.0.0.1:11434" }]
121
+ // },
122
+ // {
123
+ // "handler": "headers",
124
+ // "response": {
125
+ // "set": {
126
+ // "Access-Control-Allow-Origin": ["*"],
127
+ // "Access-Control-Allow-Methods": ["GET, POST, OPTIONS, PUT, DELETE"],
128
+ // "Access-Control-Allow-Headers": ["*"],
129
+ // "Vary": ["Origin"]
130
+ // }
131
+ // }
132
+ // }
133
+ // ]
134
+ // },
135
+ // {
136
+ // "match": [{ "host": ["a.pinokio.localhost"] }],
137
+ // "handle": [
138
+ // {
139
+ // "handler": "reverse_proxy",
140
+ // "upstreams": [{ "dial": "127.0.0.1:7860" }]
141
+ // },
142
+ // {
143
+ // "handler": "headers",
144
+ // "response": {
145
+ // "set": {
146
+ // "Access-Control-Allow-Origin": ["*"],
147
+ // "Access-Control-Allow-Methods": ["GET, POST, OPTIONS, PUT, DELETE"],
148
+ // "Access-Control-Allow-Headers": ["*"],
149
+ // "Vary": ["Origin"]
150
+ // }
151
+ // }
152
+ // }
153
+ // ]
154
+ // },
155
+ // {
156
+ // "match": [{ "host": ["b.pinokio.localhost"] }],
157
+ // "handle": [
158
+ // {
159
+ // "handler": "reverse_proxy",
160
+ // "upstreams": [{ "dial": "127.0.0.1:7861" }]
161
+ // },
162
+ // {
163
+ // "handler": "headers",
164
+ // "response": {
165
+ // "set": {
166
+ // "Access-Control-Allow-Origin": ["*"],
167
+ // "Access-Control-Allow-Methods": ["GET, POST, OPTIONS, PUT, DELETE"],
168
+ // "Access-Control-Allow-Headers": ["*"],
169
+ // "Vary": ["Origin"]
170
+ // }
171
+ // }
172
+ // }
173
+ // ]
174
+ // },
175
+ // {
176
+ // "match": [{ "host": ["c.pinokio.localhost"] }],
177
+ // "handle": [
178
+ // {
179
+ // "handler": "reverse_proxy",
180
+ // "upstreams": [{ "dial": "127.0.0.1:7862" }]
181
+ // },
182
+ // {
183
+ // "handler": "headers",
184
+ // "response": {
185
+ // "set": {
186
+ // "Access-Control-Allow-Origin": ["*"],
187
+ // "Access-Control-Allow-Methods": ["GET, POST, OPTIONS, PUT, DELETE"],
188
+ // "Access-Control-Allow-Headers": ["*"],
189
+ // "Vary": ["Origin"]
190
+ // }
191
+ // }
192
+ // }
193
+ // ]
194
+ // }
195
+ // ]
196
+ // }
302
197
  // }
303
198
  // }
304
- }
305
- }
306
-
307
-
308
-
309
-
310
- console.log("Make request to caddy", config)
311
- let response = await axios.post('http://127.0.0.1:2019/load', config, {
312
- headers: { 'Content-Type': 'application/json' }
313
- }).catch((e) => {
314
- console.log("EEEEEEEEEEEEE", e)
315
- })
316
- console.log("Caddy Response", { response })
199
+ // }
200
+ // }
201
+ //
202
+ // const config2 = {
203
+ // "apps": {
204
+ // "http": {
205
+ // "servers": {
206
+ // "main": {
207
+ // "listen": [":443"],
208
+ // //"listen": [":80"],
209
+ // "handle_response": [
210
+ // {
211
+ // "handler": "headers",
212
+ // "headers": {
213
+ // "Access-Control-Allow-Origin": ["*"],
214
+ // "Access-Control-Allow-Methods": ["GET", "POST", "OPTIONS", "PUT", "DELETE"],
215
+ // "Access-Control-Allow-Headers": ["*"]
216
+ // }
217
+ // }
218
+ // ],
219
+ // "routes": [
220
+ // {
221
+ // "match": [{ "method": ["OPTIONS"] }],
222
+ // "handle": [
223
+ // {
224
+ // "handler": "static_response",
225
+ // "headers": {
226
+ // "Access-Control-Allow-Origin": ["*"],
227
+ // "Access-Control-Allow-Methods": ["GET", "POST", "OPTIONS", "PUT", "DELETE"],
228
+ // "Access-Control-Allow-Headers": ["*"]
229
+ // },
230
+ // "status_code": 204
231
+ // }
232
+ // ]
233
+ // },
234
+ // {
235
+ // "match": [{ "host": ["pinokio.localhost"] }],
236
+ // "handle": [
237
+ // {
238
+ // "handler": "reverse_proxy",
239
+ // "upstreams": [{ "dial": "localhost:42000" }]
240
+ // }
241
+ // ]
242
+ // },
243
+ // {
244
+ // "match": [{ "host": ["l.pinokio.localhost"] }],
245
+ // "handle": [
246
+ // {
247
+ // "handler": "reverse_proxy",
248
+ // "upstreams": [{ "dial": "localhost:1234" }]
249
+ // }
250
+ // ]
251
+ // },
252
+ // {
253
+ // "match": [{ "host": ["a.pinokio.localhost"] }],
254
+ // "handle": [
255
+ // {
256
+ // "handler": "reverse_proxy",
257
+ // "upstreams": [{ "dial": "localhost:7860" }]
258
+ // }
259
+ // ]
260
+ // },
261
+ // {
262
+ // "match": [{ "host": ["b.pinokio.localhost"] }],
263
+ // "handle": [
264
+ // {
265
+ // "handler": "reverse_proxy",
266
+ // "upstreams": [{ "dial": "localhost:7861" }]
267
+ // }
268
+ // ]
269
+ // },
270
+ // {
271
+ // "match": [{ "host": ["c.pinokio.localhost"] }],
272
+ // "handle": [
273
+ // {
274
+ // "handler": "reverse_proxy",
275
+ // "upstreams": [{ "dial": "localhost:7862" }]
276
+ // }
277
+ // ]
278
+ // }
279
+ // ]
280
+ // }
281
+ // }
282
+ // },
283
+ //// "tls": {
284
+ //// "automation": {
285
+ //// "policies": [
286
+ //// {
287
+ //// "subjects": [
288
+ //// "pinokio.localhost",
289
+ //// "a.pinokio.localhost",
290
+ //// "b.pinokio.localhost",
291
+ //// "c.pinokio.localhost"
292
+ //// ],
293
+ //// "issuers": [
294
+ //// {
295
+ //// "module": "internal"
296
+ //// }
297
+ //// ]
298
+ //// }
299
+ //// ]
300
+ //// }
301
+ //// }
302
+ // }
303
+ // }
304
+ //
305
+ //
306
+ //
307
+ //
308
+ // console.log("Make request to caddy", config)
309
+ // let response = await axios.post('http://127.0.0.1:2019/load', config, {
310
+ // headers: { 'Content-Type': 'application/json' }
311
+ // }).catch((e) => {
312
+ // console.log("EEEEEEEEEEEEE", e)
313
+ // })
314
+ // console.log("Caddy Response", { response })
317
315
  }
318
316
  async install(req, ondata, kernel, id) {
319
317
  await this.kernel.bin.exec({
@@ -327,9 +325,6 @@ class Caddy {
327
325
  this.kernel.exec({
328
326
  message: `caddy run --watch`,
329
327
  path: this.kernel.homedir,
330
- kill: [{
331
- message: "caddy stop"
332
- }]
333
328
  }, (e) => {
334
329
  resolve()
335
330
  console.log("[CADDY] " + e.cleaned)
@@ -348,10 +343,6 @@ class Caddy {
348
343
  path: this.kernel.homedir
349
344
  }, (e) => {
350
345
  ondata(e)
351
- // console.log(e)
352
- // if (/Caddy Local Authority/i.test(e.cleaned)) {
353
- // trusted = true
354
- // }
355
346
  })
356
347
  } else {
357
348
  console.log("req", req)
@@ -0,0 +1,193 @@
1
+ const axios = require('axios')
2
+ const path = require('path')
3
+ class Caddy {
4
+ constructor(kernel) {
5
+ this.kernel = kernel
6
+ }
7
+ async update() {
8
+ this.mapping = {}
9
+ let payload = await this.payload()
10
+ console.log("Make request to caddy", JSON.stringify(payload, null, 2))
11
+ let response = await axios.post('http://127.0.0.1:2019/load', payload, {
12
+ headers: { 'Content-Type': 'application/json' }
13
+ }).catch((e) => {
14
+ console.log("EEEEEEEEEEEEE", e)
15
+ })
16
+ console.log("Caddy Response", { response })
17
+ }
18
+ async procs (payload) {
19
+ console.log("####### procs", payload)
20
+ let list = this.kernel.processes.list
21
+ if (!list) {
22
+ list = await this.kernel.processes.refresh()
23
+ }
24
+ for(let item of list) {
25
+ let url = `${item.port}.localhost`
26
+ this.mapping[item.ip] = url
27
+ payload.apps.http.servers.main.routes.push({
28
+ "match": [{
29
+ "host": [url],
30
+ }],
31
+ "handle": [
32
+ {
33
+ "handler": "reverse_proxy",
34
+ "upstreams": [{ "dial": item.ip }]
35
+ },
36
+ {
37
+ "handler": "headers",
38
+ "response": {
39
+ "set": {
40
+ "Access-Control-Allow-Origin": ["*"],
41
+ "Access-Control-Allow-Methods": ["GET, POST, OPTIONS, PUT, DELETE"],
42
+ "Access-Control-Allow-Headers": ["*"],
43
+ "Vary": ["Origin"]
44
+ }
45
+ }
46
+ }
47
+ ]
48
+ })
49
+ }
50
+ return payload
51
+ }
52
+ locals (payload) {
53
+ // construct Caddy update payload
54
+ let local = this.kernel.memory.local;
55
+ console.log({ local })
56
+ for(let script_path in local) {
57
+ let local_variables = local[script_path]
58
+ console.log({ local_variables })
59
+ for(let key in local_variables) {
60
+ let val = local_variables[key]
61
+ if (val.startsWith("http")) {
62
+ val = val.replace(/https?:\/\//, '')
63
+ let api_path = this.kernel.path("api")
64
+ let rel_path = path.relative(api_path, script_path)
65
+ let name = rel_path.split(path.sep)[0]
66
+ console.log({ api_path, rel_path, name, val })
67
+ if (key === "url") {
68
+ let url = `${name}.localhost`.toLowerCase()
69
+ this.mapping[val] = url
70
+ payload.apps.http.servers.main.routes.push({
71
+ "match": [{
72
+ "host": [url]
73
+ //"path": [`/local/${key}/${uri}/*`]
74
+ }],
75
+ "handle": [
76
+ //{
77
+ // "handler": "rewrite",
78
+ // "uri": "/"
79
+ //},
80
+ {
81
+ "handler": "reverse_proxy",
82
+ "upstreams": [{ "dial": val }]
83
+ },
84
+ {
85
+ "handler": "headers",
86
+ "response": {
87
+ "set": {
88
+ "Access-Control-Allow-Origin": ["*"],
89
+ "Access-Control-Allow-Methods": ["GET, POST, OPTIONS, PUT, DELETE"],
90
+ "Access-Control-Allow-Headers": ["*"],
91
+ "Vary": ["Origin"]
92
+ }
93
+ }
94
+ }
95
+ ]
96
+ })
97
+ }
98
+ payload.apps.http.servers.main.routes.push({
99
+ "match": [{
100
+ "host": [`${key}.${name}.localhost`.toLowerCase()],
101
+ //"path": [`/local/${key}/${uri}/*`]
102
+ }],
103
+ "handle": [
104
+ //{
105
+ // "handler": "rewrite",
106
+ // "uri": "/"
107
+ //},
108
+ {
109
+ "handler": "reverse_proxy",
110
+ "upstreams": [{ "dial": val }]
111
+ },
112
+ {
113
+ "handler": "headers",
114
+ "response": {
115
+ "set": {
116
+ "Access-Control-Allow-Origin": ["*"],
117
+ "Access-Control-Allow-Methods": ["GET, POST, OPTIONS, PUT, DELETE"],
118
+ "Access-Control-Allow-Headers": ["*"],
119
+ "Vary": ["Origin"]
120
+ }
121
+ }
122
+ }
123
+ ]
124
+ })
125
+ }
126
+ }
127
+ }
128
+ return payload
129
+ }
130
+ home () {
131
+ return {
132
+ "apps": {
133
+ "http": {
134
+ "servers": {
135
+ "main": {
136
+ //"listen": ["127.0.0.1:443"],
137
+ "listen": [":443"],
138
+ "routes": [
139
+ {
140
+ "match": [{ "method": ["OPTIONS"] }],
141
+ "handle": [
142
+ {
143
+ "handler": "headers",
144
+ "response": {
145
+ "set": {
146
+ "Access-Control-Allow-Origin": ["*"],
147
+ "Access-Control-Allow-Methods": ["GET, POST, OPTIONS, PUT, DELETE"],
148
+ "Access-Control-Allow-Headers": ["*"],
149
+ "Vary": ["Origin"]
150
+ }
151
+ }
152
+ },
153
+ {
154
+ "handler": "static_response",
155
+ "status_code": 204
156
+ }
157
+ ]
158
+ },
159
+ {
160
+ "match": [{ "host": ["pinokio.localhost"] }],
161
+ "handle": [
162
+ {
163
+ "handler": "reverse_proxy",
164
+ "upstreams": [{ "dial": "127.0.0.1:42000" }]
165
+ },
166
+ {
167
+ "handler": "headers",
168
+ "response": {
169
+ "set": {
170
+ "Access-Control-Allow-Origin": ["*"],
171
+ "Access-Control-Allow-Methods": ["GET, POST, OPTIONS, PUT, DELETE"],
172
+ "Access-Control-Allow-Headers": ["*"],
173
+ "Vary": ["Origin"]
174
+ }
175
+ }
176
+ }
177
+ ]
178
+ },
179
+ ]
180
+ }
181
+ }
182
+ }
183
+ }
184
+ }
185
+ }
186
+ async payload () {
187
+ let payload = this.home()
188
+ payload = this.locals(payload)
189
+ payload = await this.procs(payload)
190
+ return payload
191
+ }
192
+ }
193
+ module.exports = Caddy
package/kernel/index.js CHANGED
@@ -30,6 +30,8 @@ const Pipe = require("../pipe")
30
30
  const Cloudflare = require('./api/cloudflare')
31
31
  const Store = require('./store')
32
32
  const Proto = require('./prototype')
33
+ const Caddy = require("./caddy")
34
+ const Procs = require('./procs')
33
35
  const VARS = {
34
36
  pip: {
35
37
  install: {
@@ -80,6 +82,7 @@ class Kernel {
80
82
  this.info = new Info(this)
81
83
  this.pipe = new Pipe(this)
82
84
  this.proto = new Proto(this)
85
+ this.processes = new Procs()
83
86
  this.kv = new KV(this)
84
87
  this.cloudflare = new Cloudflare()
85
88
  this.shellpath = shellPath.sync()
@@ -488,6 +491,7 @@ class Kernel {
488
491
  this.api = new Api(this)
489
492
  this.python = new Python(this)
490
493
  this.shell = new Shells(this)
494
+ this.caddy = new Caddy(this)
491
495
  this.system = system
492
496
  this.keys = {}
493
497
  this.memory = {
@@ -0,0 +1,113 @@
1
+ const os = require('os')
2
+ const path = require('path')
3
+ const { fork, exec } = require('child_process');
4
+ const platform = os.platform();
5
+ class Procs {
6
+ constructor () {
7
+ console.log("Initializing procs")
8
+ }
9
+ getPortPidList(callback) {
10
+ const isWin = platform === 'win32';
11
+ const cmd = isWin ? 'netstat -ano -p tcp' : 'lsof -nP -iTCP -sTCP:LISTEN';
12
+ exec(cmd, (err, stdout) => {
13
+ if (err) return callback(err);
14
+
15
+ const results = [];
16
+ let pids = new Set()
17
+ const lines = stdout.trim().split('\n');
18
+
19
+ lines.forEach(line => {
20
+ console.log({ line })
21
+ if (isWin) {
22
+ // Skip headers
23
+ if (!line.startsWith(' TCP')) return;
24
+ const parts = line.trim().split(/\s+/);
25
+ const [ , localAddress, , state, pid ] = parts;
26
+ if (pids.has(pid)) return;
27
+ pids.add(pid)
28
+ if (state !== 'LISTENING') return;
29
+ const chunks = localAddress.split(":")
30
+ const port = chunks.pop()
31
+ let ip = chunks.pop()
32
+ if (!ip || ip === "*") {
33
+ ip = "127.0.0.1:" + port
34
+ } else {
35
+ ip = localAddress
36
+ }
37
+ results.push({ port, pid, ip });
38
+ } else {
39
+ if (!/LISTEN/.test(line)) return;
40
+ const parts = line.trim().split(/\s+/);
41
+ const pid = parts[1];
42
+ if (pids.has(pid)) return;
43
+ pids.add(pid)
44
+
45
+ const match = line.match(/([^\s]+:\d+)\s/);
46
+ const localAddress = match?.[1];
47
+ const chunks = localAddress.split(":")
48
+ const port = chunks.pop()
49
+ let ip = chunks.pop()
50
+ if (!ip || ip === "*") {
51
+ ip = "127.0.0.1:" + port
52
+ } else {
53
+ ip = localAddress
54
+ }
55
+ //const portMatch = line.match(/:(\d+)\s/);
56
+ //const port = portMatch?.[1];
57
+ if (pid && port) results.push({ port, pid, ip });
58
+ }
59
+ });
60
+
61
+ callback(null, results);
62
+ });
63
+ }
64
+ getPidToNameMap(callback) {
65
+ const isWin = platform === 'win32';
66
+ const cmd = isWin ? 'tasklist /fo csv /nh' : 'ps -Ao pid,comm';
67
+ exec(cmd, (err, stdout) => {
68
+ if (err) return callback(err);
69
+ const lines = stdout.trim().split('\n');
70
+ const map = {};
71
+ lines.forEach(line => {
72
+ if (isWin) {
73
+ const [name, , , , pid] = line.split('","').map(s => s.replace(/(^"|"$)/g, ''));
74
+ map[pid] = name;
75
+ } else {
76
+ const [pid, ...nameParts] = line.trim().split(/\s+/);
77
+ map[pid] = nameParts.join(' ');
78
+ }
79
+ });
80
+ callback(null, map);
81
+ });
82
+ }
83
+ async refresh() {
84
+ console.time("Get list")
85
+ let list = await new Promise((resolve, reject) => {
86
+ this.getPortPidList((err, portPidList) => {
87
+ if (err) {
88
+ reject(err)
89
+ return
90
+ }
91
+
92
+ this.getPidToNameMap((err, pidToName) => {
93
+ if (err) {
94
+ reject(err)
95
+ return
96
+ }
97
+
98
+ let list = portPidList.map(({ port, pid, ip }) => {
99
+ const fullname = pidToName[pid] || 'Unknown';
100
+ const name = fullname.split(path.sep).pop()
101
+ return { port, pid , name, fullname, ip }
102
+ })
103
+ resolve(list)
104
+ });
105
+ });
106
+ })
107
+ console.log( { list } )
108
+ console.timeEnd("Get list")
109
+ this.list = list
110
+ return this.list
111
+ }
112
+ }
113
+ module.exports = Procs
package/kernel/shell.js CHANGED
@@ -2,7 +2,7 @@ const { Terminal } = require('xterm-headless');
2
2
  const { SerializeAddon } = require("xterm-addon-serialize");
3
3
  const sanitize = require("sanitize-filename");
4
4
  const YAML = require('yaml')
5
-
5
+ const kill = require('tree-kill');
6
6
  const fastq = require('fastq')
7
7
  const { v4: uuidv4 } = require('uuid');
8
8
  const os = require('os');
@@ -60,8 +60,6 @@ class Shell {
60
60
 
61
61
  }
62
62
  async init_env(params) {
63
- console.log({ params })
64
- console.time("> 1")
65
63
  this.env = Object.assign({}, process.env)
66
64
  // If the user has set PYTHONPATH, unset it.
67
65
  if (this.env.PYTHONPATH) {
@@ -90,16 +88,12 @@ class Shell {
90
88
  // }
91
89
  for(let key in this.env) {
92
90
  if (key.startsWith("CUDA")) {
93
- console.log("Unset env key: " + key)
94
91
  delete this.env[key]
95
92
  }
96
93
  if (/.*(SSH|SSL).*/.test(key)) {
97
- console.log("Unset env key: " + key)
98
94
  delete this.env[key]
99
95
  }
100
96
  }
101
- console.timeEnd("> 1")
102
- console.time("> 2")
103
97
 
104
98
  this.env.CMAKE_OBJECT_PATH_MAX = 1024
105
99
  this.env.PYTORCH_ENABLE_MPS_FALLBACK = 1
@@ -113,9 +107,7 @@ class Shell {
113
107
  // First override this.env with system env
114
108
  let system_env = await Environment.get(this.kernel.homedir)
115
109
  this.env = Object.assign(this.env, system_env)
116
- console.timeEnd("> 2")
117
110
 
118
- console.time("> 3")
119
111
  // if the shell is running from a script file, the params.$parent will include the path to the parent script
120
112
  // this means we need to apply app environment as well
121
113
  if (params.$parent) {
@@ -147,7 +139,6 @@ class Shell {
147
139
 
148
140
  if (this.platform === "linux") {
149
141
  let gxx = this.kernel.which('g++')
150
- console.log({ gxx })
151
142
  if (gxx) {
152
143
  this.env.NVCC_PREPEND_FLAGS = `-ccbin ${gxx}`
153
144
  }
@@ -156,8 +147,6 @@ class Shell {
156
147
  this.env[PATH_KEY] = this.env[PATH_KEY] + path.delimiter + path.resolve(this.kernel.homedir, 'bin')
157
148
 
158
149
 
159
- console.timeEnd("> 3")
160
- console.time("> 4")
161
150
  if (params.env) {
162
151
  for(let key in params.env) {
163
152
  // iterate through the env attributes
@@ -191,10 +180,6 @@ class Shell {
191
180
  }
192
181
  }
193
182
  }
194
- console.timeEnd("> 4")
195
-
196
-
197
- console.time("> 5")
198
183
  for(let key in this.env) {
199
184
  if (!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(key) && key !== "ProgramFiles(x86)") {
200
185
  delete this.env[key]
@@ -213,7 +198,6 @@ class Shell {
213
198
  delete this.env[key]
214
199
  }
215
200
  }
216
- console.timeEnd("> 5")
217
201
  }
218
202
  async start(params, ondata) {
219
203
  this.ondata = ondata
@@ -245,9 +229,6 @@ class Shell {
245
229
  this.rows = params.client.rows
246
230
  }
247
231
 
248
- console.log({ cols: this.cols, rows: this.rows })
249
-
250
-
251
232
  this.vt = new Terminal({
252
233
  allowProposedApi: true,
253
234
  cols: this.cols,
@@ -280,13 +261,13 @@ class Shell {
280
261
  if (params.sudo) {
281
262
  let options = {
282
263
  name: "Pinokio",
283
- env: {}
264
+ // env: {}
284
265
  // icns: '/Applications/Electron.app/Contents/Resources/Electron.icns', // (optional)
285
266
  };
286
267
 
287
- for(let key in this.env) {
288
- options.env[key] = String(this.env[key])
289
- }
268
+ // for(let key in this.env) {
269
+ // options.env[key] = String(this.env[key])
270
+ // }
290
271
 
291
272
  // sudo-prompt uses TEMP
292
273
  await fs.promises.mkdir(this.env.TEMP, { recursive: true }).catch((e) => { })
@@ -297,7 +278,6 @@ class Shell {
297
278
  // Modify process.env (and need to immediately revert it back to original process.env so as to not affect other logic)
298
279
  let old_env = process.env
299
280
  process.env = this.env
300
- console.log("sudo process.env", process.env)
301
281
  sudo.exec(params.message, options, (err, stdout, stderr) => {
302
282
  if (err) {
303
283
  console.log("SUDOPROMPT ERR", err)
@@ -343,7 +323,6 @@ class Shell {
343
323
  return;
344
324
  }
345
325
  let chunk = message.slice(i, i+1024)
346
- console.log("Writing chunk", chunk)
347
326
  this.ptyProcess.write(chunk)
348
327
  i += 1024;
349
328
  }, 10);
@@ -972,14 +951,7 @@ class Shell {
972
951
  this.ondata({ raw: `\r\n\r\n██ Detached from Shell ${this.id}\r\n\r\n` })
973
952
  }
974
953
  }
975
- runSequentially(tasks) {
976
- let chain = Promise.resolve();
977
- for (const task of tasks) {
978
- chain = chain.then(() => task());
979
- }
980
- return chain;
981
- }
982
- kill(message, force) {
954
+ kill(message, force, cb) {
983
955
  console.log("KILL")
984
956
 
985
957
  this.done = true
@@ -1004,36 +976,24 @@ class Shell {
1004
976
  this.vt.dispose()
1005
977
  this.queue.killAndDrain()
1006
978
  if (this.ptyProcess) {
1007
- if (this.kill_messages) {
1008
- console.log({ kill_messages: this.kill_messages })
1009
- let promises = this.kill_messages.map((m) => {
1010
- return new Promise(async (resolve, reject) => {
1011
- await this.kernel.exec(m, this.ondata)
1012
- resolve()
1013
- })
1014
- })
1015
- this.runSequentially(promises).then(() => {
1016
- console.log("Running kill message", { kill_messages })
1017
- this.ptyProcess.write(kill_messages)
979
+ if (cb) {
980
+ console.log("tree kill", this.ptyProcess.pid)
981
+ kill(this.ptyProcess.pid, 'SIGKILL', () => {
1018
982
  this.ptyProcess.kill()
1019
983
  this.ptyProcess = undefined
1020
- // automatically remove the shell from this.kernel.shells
1021
- this.kernel.shell.rm(this.id)
1022
- this.ondata({ raw: `\r\n\r\n██ Terminated Shell ${this.id}\r\n████\r\n` })
1023
- })
984
+ cb()
985
+ });
1024
986
  } else {
987
+ console.log("tree kill", this.ptyProcess.pid)
988
+ kill(this.ptyProcess.pid, 'SIGKILL');
1025
989
  this.ptyProcess.kill()
1026
990
  this.ptyProcess = undefined
1027
- // automatically remove the shell from this.kernel.shells
1028
- this.kernel.shell.rm(this.id)
1029
- this.ondata({ raw: `\r\n\r\n██ Terminated Shell ${this.id}\r\n████\r\n` })
1030
991
  }
1031
- } else {
1032
- // automatically remove the shell from this.kernel.shells
1033
- this.kernel.shell.rm(this.id)
1034
- this.ondata({ raw: `\r\n\r\n██ Terminated Shell ${this.id}\r\n████\r\n` })
1035
992
  }
1036
993
 
994
+ // automatically remove the shell from this.kernel.shells
995
+ this.kernel.shell.rm(this.id)
996
+ this.ondata({ raw: `\r\n\r\n██ Terminated Shell ${this.id}\r\n████\r\n` })
1037
997
 
1038
998
  }
1039
999
  log() {
package/kernel/shells.js CHANGED
@@ -358,7 +358,7 @@ class Shells {
358
358
  stop (request, message) {
359
359
  return this.kill(request, message)
360
360
  }
361
- reset() {
361
+ reset(cb) {
362
362
  let info = this.shells.map((s) => {
363
363
  return { id: s.id, group: s.group, cmd: s.cmd }
364
364
  })
@@ -367,9 +367,19 @@ class Shells {
367
367
  for(let i=0; i<this.shells.length; i++) {
368
368
  shells.push(this.shells[i])
369
369
  }
370
+ let count = 0
370
371
  for(let shell of shells) {
371
372
  console.log("[Kill Shell]", { id: shell.id, group: shell.group, cmd: shell.cmd })
372
- shell.kill("", true)
373
+ if (cb) {
374
+ shell.kill("", true, () => {
375
+ count++
376
+ if (count >= shells.length) {
377
+ cb()
378
+ }
379
+ })
380
+ } else {
381
+ shell.kill("", true)
382
+ }
373
383
  }
374
384
  }
375
385
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pinokiod",
3
- "version": "3.8.22",
3
+ "version": "3.8.24",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -47,6 +47,7 @@
47
47
  "multer": "^1.4.5-lts.1",
48
48
  "node-downloader-helper": "^2.1.9",
49
49
  "node-gradio-client": "^0.14.6",
50
+ "node-netstat": "^1.9.0",
50
51
  "pdrive": "^0.0.26",
51
52
  "portfinder-cp": "^1.0.34",
52
53
  "proxy-agent": "^6.5.0",
@@ -60,6 +61,7 @@
60
61
  "sudo-prompt-programfiles-x86": "^9.2.10",
61
62
  "symlink-dir": "^5.2.1",
62
63
  "systeminformation": "^5.18.4",
64
+ "tree-kill": "^1.2.2",
63
65
  "uuid": "^9.0.0",
64
66
  "wait-on": "^7.2.0",
65
67
  "which": "^5.0.0",
package/server/index.js CHANGED
@@ -13,12 +13,13 @@ const cors = require('cors');
13
13
  const path = require("path")
14
14
  const fs = require('fs');
15
15
  const os = require('os')
16
- const { fork } = require('child_process');
16
+ const { fork, exec } = require('child_process');
17
17
  const semver = require('semver')
18
18
  const fse = require('fs-extra')
19
19
  const QRCode = require('qrcode')
20
20
  const axios = require('axios')
21
21
 
22
+
22
23
  const git = require('isomorphic-git')
23
24
  const http = require('isomorphic-git/http/node')
24
25
  const marked = require('marked')
@@ -2658,6 +2659,15 @@ class Server {
2658
2659
  })
2659
2660
  }))
2660
2661
  this.app.get("/proxy", ex(async (req, res) => {
2662
+ let list = await this.kernel.processes.refresh()
2663
+ list = list.map((item) => {
2664
+ return {
2665
+ proxy: this.kernel.caddy.mapping[item.ip],
2666
+ ...item
2667
+ }
2668
+ })
2669
+ await this.kernel.caddy.update()
2670
+
2661
2671
  let live_proxies = this.kernel.api.proxies["/proxy"]
2662
2672
  if (!live_proxies) live_proxies = []
2663
2673
  let proxies = []
@@ -2735,6 +2745,7 @@ class Server {
2735
2745
  }
2736
2746
  }
2737
2747
  res.render("proxy", {
2748
+ list,
2738
2749
  agent: this.agent,
2739
2750
  theme: this.theme,
2740
2751
  items: proxies,
@@ -3846,13 +3857,19 @@ class Server {
3846
3857
  });
3847
3858
  process.on('SIGINT', () => {
3848
3859
  console.log("SIGINT Event")
3849
- if (this.kernel && this.kernel.shell) this.kernel.shell.reset()
3850
- process.exit()
3860
+ if (this.kernel && this.kernel.shell) {
3861
+ this.kernel.shell.reset(() => {
3862
+ process.exit()
3863
+ })
3864
+ }
3851
3865
  })
3852
3866
  process.on('SIGTERM', () => {
3853
3867
  console.log("SIGTERM Event")
3854
- if (this.kernel && this.kernel.shell) this.kernel.shell.reset()
3855
- process.exit()
3868
+ if (this.kernel && this.kernel.shell) {
3869
+ this.kernel.shell.reset(() => {
3870
+ process.exit()
3871
+ })
3872
+ }
3856
3873
  })
3857
3874
  // process.on('exit', () => {
3858
3875
  // console.log("exit Event")
@@ -82,6 +82,10 @@ header .runner {
82
82
  font-size: 14px;
83
83
  margin-bottom: 3px;
84
84
  }
85
+ .line.align-top h3.table-grid {
86
+ display: grid;
87
+ grid-template-columns: repeat(3, 1fr);
88
+ }
85
89
  .browser-options-row .btn.disabled {
86
90
  opacity: 0.7;
87
91
  }
@@ -157,7 +161,7 @@ body.dark .browser-options-row {
157
161
  }
158
162
  .container {
159
163
  display: grid;
160
- grid-template-columns: repeat(2, 1fr);
164
+ grid-template-columns: repeat(3, 1fr);
161
165
  }
162
166
  .dark .container-row {
163
167
  background: rgba(255, 255, 255, 0.04);
@@ -206,6 +210,25 @@ body.dark .browser-options-row {
206
210
  <div class='header-label'><i class='fa-solid fa-wifi'></i> Local Sharing</div>
207
211
  <div class='desc'>Serve Pinokio, installed apps, and even external apps to any device on the same network.</div>
208
212
  <div class='container'>
213
+ <div class='container-row'>
214
+ <div class='header-label-sub'><i class="fa-solid fa-microchip"></i> Apps</div>
215
+ <div class='line align-top'>
216
+ <h3 class='table-grid'>
217
+ <div class='col'>Name</div>
218
+ <div class='col'>Pid</div>
219
+ <div class='col'>Port</div>
220
+ </h3>
221
+ </div>
222
+ <% list.forEach((item) => { %>
223
+ <a target="_blank" href="https://<%=item.proxy%>" class='line align-top'>
224
+ <h3 class='table-grid'>
225
+ <div class='col'><%=item.name%></div>
226
+ <div class='col'><%=item.pid%></div>
227
+ <div class='col'><%=item.port%></div>
228
+ </h3>
229
+ </a>
230
+ <% }) %>
231
+ </div>
209
232
  <div class='container-row'>
210
233
  <div class='header-label-sub'><i class="fa-solid fa-microchip"></i> System Programs</div>
211
234
  <div class='line align-top'>