clavarium 0.1.0-next.8 → 0.1.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/README.md +7 -5
- package/deploy/install.sh +1 -1
- package/deploy/online.mjs +38 -5
- package/npm-shrinkwrap.json +2 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -216,11 +216,13 @@ The host needs `tmux` and `bindfs` (the read-only views).
|
|
|
216
216
|
# the stable version from npm, in local mode, asking nothing (Node.js pinned and
|
|
217
217
|
# checked first); it prints the next command and the public keys (text and QR)
|
|
218
218
|
curl -fsSL https://clavarium.org/install.sh | sudo bash
|
|
219
|
-
# online in the same line: it installs, shows the setup key (text and QR),
|
|
220
|
-
#
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
219
|
+
# online in the same line: it installs, shows the setup key (text and QR), asks for the
|
|
220
|
+
# relay's address once you made it with that key, waits for your DNS, sets the relay up
|
|
221
|
+
# over SSH, tests from the internet, shows the password once
|
|
222
|
+
DOMAIN=<your-domain>
|
|
223
|
+
EMAIL=<your-email>
|
|
224
|
+
curl -fsSL https://clavarium.org/install.sh | sudo bash -s -- --domain "$DOMAIN" --admin "$EMAIL" --relay-user ubuntu
|
|
225
|
+
curl -fsSL https://clavarium.org/install.sh | sudo bash -s -- --direct --domain "$DOMAIN"
|
|
224
226
|
# or later, from local mode
|
|
225
227
|
sudo clavarium online --relay relay.example.net --domain clav.example.com
|
|
226
228
|
sudo clavarium online --port --domain clav.example.com
|
package/deploy/install.sh
CHANGED
|
@@ -701,7 +701,7 @@ elif [ -n "$RELAY" ]; then
|
|
|
701
701
|
# It is a PUBLIC key: showing it is safe; it lets the relay know this machine.
|
|
702
702
|
if command -v qrencode >/dev/null 2>&1 || apt-get install -y -qq qrencode >/dev/null 2>&1; then
|
|
703
703
|
echo "The same key, to read with a phone or a tablet:"
|
|
704
|
-
qrencode -t
|
|
704
|
+
qrencode -t ANSI -m 1 -l L -- "$TUNNEL_KEY" || true
|
|
705
705
|
fi
|
|
706
706
|
echo "It will print this, and it must be the same: $RELAY_PRINT"
|
|
707
707
|
echo "The name $DOMAIN must lead to the relay."
|
package/deploy/online.mjs
CHANGED
|
@@ -63,7 +63,7 @@ export const USAGE = [
|
|
|
63
63
|
].join('\n');
|
|
64
64
|
|
|
65
65
|
export function parseOnline(args) {
|
|
66
|
-
const o = { relay: '', user: 'root', relayPort: '22', domain: '', admin: '', fingerprint: '', keepSetupKey: false, yes: false, port: false };
|
|
66
|
+
const o = { askRelay: false, relay: '', user: 'root', relayPort: '22', domain: '', admin: '', fingerprint: '', keepSetupKey: false, yes: false, port: false };
|
|
67
67
|
const value = (i, name) => { const v = args[i + 1]; if (v === undefined || v.startsWith('--')) throw new Bad(`${name} needs a value`); return v; };
|
|
68
68
|
for (let i = 0; i < args.length; i++) {
|
|
69
69
|
const a = args[i];
|
|
@@ -80,12 +80,15 @@ export function parseOnline(args) {
|
|
|
80
80
|
default: throw new Bad(`unknown parameter: ${a}`);
|
|
81
81
|
}
|
|
82
82
|
}
|
|
83
|
-
if (
|
|
83
|
+
if (o.relay && o.port) throw new Bad('say how it will be reached: --relay HOST or --port, not both');
|
|
84
|
+
/* Neither: through a relay that does not exist yet -- its key is shown first,
|
|
85
|
+
and its address asked once the operator has made it with that key. */
|
|
86
|
+
if (!o.relay && !o.port) o.askRelay = true;
|
|
84
87
|
if (!DOMAIN.test(o.domain)) throw new Bad('--domain is a host name, lower case, like clav.example.com');
|
|
85
88
|
o.admin ||= `admin@${o.domain}`;
|
|
86
89
|
if (!EMAIL.test(o.admin)) throw new Bad('--admin is an e-mail address, lower case');
|
|
87
|
-
if (o.relay) {
|
|
88
|
-
if (!HOST.test(o.relay)) throw new Bad('--relay is the name or the address of the relay machine');
|
|
90
|
+
if (o.relay || o.askRelay) {
|
|
91
|
+
if (o.relay && !HOST.test(o.relay)) throw new Bad('--relay is the name or the address of the relay machine');
|
|
89
92
|
if (!USER.test(o.user)) throw new Bad('--relay-user is an account name');
|
|
90
93
|
if (!/^\d{1,5}$/.test(o.relayPort) || +o.relayPort < 1 || +o.relayPort > 65535) throw new Bad('--relay-port is a port number');
|
|
91
94
|
if (o.fingerprint && !PRINT.test(o.fingerprint)) throw new Bad('--relay-fingerprint looks like SHA256:... (ssh-keygen -lf /etc/ssh/ssh_host_ed25519_key.pub on the relay)');
|
|
@@ -121,7 +124,7 @@ export async function ensureKeys(sys, P = PATHS) {
|
|
|
121
124
|
}
|
|
122
125
|
|
|
123
126
|
async function qr(sys, text) {
|
|
124
|
-
const r = await sys.run(['qrencode', '-t', '
|
|
127
|
+
const r = await sys.run(['qrencode', '-t', 'ANSI', '-m', '1', '-l', 'L', '--', text]);
|
|
125
128
|
if (r.code === 0 && r.out) sys.print(r.out.replace(/\n$/, ''));
|
|
126
129
|
}
|
|
127
130
|
|
|
@@ -216,6 +219,19 @@ export async function checkDns(sys, o) {
|
|
|
216
219
|
return got;
|
|
217
220
|
}
|
|
218
221
|
|
|
222
|
+
/* The domain made to point to the relay while the operator is at it: waited for
|
|
223
|
+
(every 30 s, Enter to look now), the record to make said once. */
|
|
224
|
+
export async function waitDns(sys, o) {
|
|
225
|
+
let said = false;
|
|
226
|
+
for (;;) {
|
|
227
|
+
const relay = await addresses(sys, o.relay);
|
|
228
|
+
const got = await addresses(sys, o.domain);
|
|
229
|
+
if (relay.length && got.some((a) => relay.includes(a))) return;
|
|
230
|
+
if (!said && relay.length) { said = true; sys.print(`At your DNS provider, point the domain to the relay:\n ${o.domain} A ${relay[0]}\nWaiting for it (it takes a few minutes) -- or press Enter to look now.`); }
|
|
231
|
+
await (sys.sleepOrEnter ? sys.sleepOrEnter(30_000) : sys.sleep(30_000));
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
|
|
219
235
|
/* ------------------------ the test from the internet ------------------------ */
|
|
220
236
|
/* What Let's Encrypt (or Caddy) said, as the operator needs to read it. */
|
|
221
237
|
export function explain(error, { domain, port, relay }) {
|
|
@@ -437,6 +453,17 @@ export async function online(o, sys, P = PATHS) {
|
|
|
437
453
|
if (was) throw new Refused(`this machine is in server mode already: https://${was}`);
|
|
438
454
|
if (!existsSync(P.caddy)) throw new Failed('the HTTPS programs are not on this machine: run the installer again (curl -fsSL https://clavarium.org/install.sh | sudo bash)');
|
|
439
455
|
const keys = await ensureKeys(sys, P);
|
|
456
|
+
if (o.askRelay) {
|
|
457
|
+
await showKeys(sys, P, { which: 'setup' });
|
|
458
|
+
sys.print('Create the relay at your host now (Ubuntu), with the key above as its SSH key.');
|
|
459
|
+
for (;;) {
|
|
460
|
+
const a = String(await sys.askLine('Its address, once it exists (IP or name): ') ?? '').trim();
|
|
461
|
+
if (HOST.test(a)) { o.relay = a; break; }
|
|
462
|
+
if (!a && !sys.hasKeyboard?.()) throw new Failed('no keyboard to ask on: give --relay HOST');
|
|
463
|
+
sys.print(' That is not an address: an IP address, or a name like relay.example.com');
|
|
464
|
+
}
|
|
465
|
+
await waitDns(sys, o);
|
|
466
|
+
}
|
|
440
467
|
await checkDns(sys, o);
|
|
441
468
|
await portsFree(sys);
|
|
442
469
|
if (o.relay) await setUpRelay(sys, P, o, keys);
|
|
@@ -515,6 +542,12 @@ export function realSys() {
|
|
|
515
542
|
timer = setTimeout(done, ms);
|
|
516
543
|
try { tty = createReadStream('/dev/tty'); tty.on('data', (d) => { if (d.includes(10) || d.includes(13)) done(); }); tty.on('error', () => {}); } catch { /* no keyboard: the timer alone */ }
|
|
517
544
|
}),
|
|
545
|
+
hasKeyboard: () => { try { closeSync(openSync('/dev/tty', 'r')); return true; } catch { return false; } },
|
|
546
|
+
askLine: async (question) => {
|
|
547
|
+
let fd;
|
|
548
|
+
try { fd = openSync('/dev/tty', 'r+'); } catch { return ''; }
|
|
549
|
+
try { writeSync(fd, question); const buf = Buffer.alloc(512); let s = ''; while (!s.includes('\n')) { const n = readSync(fd, buf, 0, buf.length, null); if (!n) break; s += buf.toString('utf8', 0, n); } return s.split('\n')[0]; } finally { closeSync(fd); }
|
|
550
|
+
},
|
|
518
551
|
waitEnter: async () => {
|
|
519
552
|
let fd;
|
|
520
553
|
try { fd = openSync('/dev/tty', 'r'); } catch { return false; }
|
package/npm-shrinkwrap.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "clavarium",
|
|
3
|
-
"version": "0.1.0
|
|
3
|
+
"version": "0.1.0",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "clavarium",
|
|
9
|
-
"version": "0.1.0
|
|
9
|
+
"version": "0.1.0",
|
|
10
10
|
"license": "MIT",
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"@xterm/addon-fit": "^0.11.0",
|