@inoku/lepan 0.7.66 → 0.7.69
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 +16 -1
- package/USER_MANUAL.md +28 -12
- package/bin/lifedrive.js +49 -22
- package/dist/lifedrive-bundle.tar.gz +2 -2
- package/dist/lifedrive-bundle.tar.gz.sha256 +1 -1
- package/dist/lifedrive-install.ps1 +7 -1
- package/dist/lifedrive-install.sh +13 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -86,7 +86,7 @@ The Linux/macOS legacy browser-owner setup uses the built-in AV1 registration en
|
|
|
86
86
|
|
|
87
87
|
LifeDrive requires Leither V0.24.11 or newer. Linux/macOS browser-owner setup creates a separate Ed25519 `sodiumv2` identity for the primary browser. Windows prints a private ten-minute invitation for the first paired phone; later users and devices are managed from a paired device.
|
|
88
88
|
|
|
89
|
-
After successful npm setup, the installer
|
|
89
|
+
After successful npm setup, the installer displays the QR code at the end of its output whenever the terminal is wide enough. If the whole code cannot fit on screen, it automatically opens the full-size QR image in the computer's image viewer. In the iPhone or Android app, open **Settings → Set up users → Scan QR code** and scan the displayed code. A private `lepan-pairing-<id>.png` is also saved, with its path printed as a fallback for remote sessions or computers without an image viewer. A private `.json` invitation is saved alongside it for apps without a setup scanner: transfer that file to the phone and use **Choose identity file**. These files are saved in the Leither root on Linux/macOS and its private `.lifedrive-household` directory on Windows. Household invitations expire ten minutes after creation; legacy identity codes contain a device private key, so keep them private and delete the transfer copies after pairing. Legacy `--add-device` and `--upgrade` also produce a code when an identity is available; household upgrades preserve existing pairings without issuing new invitations.
|
|
90
90
|
|
|
91
91
|
### Renew an expired first-phone invitation
|
|
92
92
|
|
|
@@ -112,6 +112,21 @@ already exist, use **My devices** on a paired phone to invite another device. An
|
|
|
112
112
|
interrupted first claim must be resumed on the original phone with its original
|
|
113
113
|
invitation. Ordinary `--upgrade` does not renew invitations.
|
|
114
114
|
|
|
115
|
+
### Reconnect after forgetting the only phone
|
|
116
|
+
|
|
117
|
+
Run `npx --yes @inoku/lepan@latest --recover-device Owner` on the computer hosting
|
|
118
|
+
Leither, substituting the existing account name or user ID. Scan the displayed
|
|
119
|
+
QR code to reconnect to that same account. This node-operator action preserves
|
|
120
|
+
account keys, files, backups, and other devices. The reconnect invitation is
|
|
121
|
+
private and expires in ten minutes; rerun the same command if it expires before
|
|
122
|
+
being claimed. The account service briefly restarts, while Leither keeps running.
|
|
123
|
+
Normal phone-to-phone invitations still require device-manager approval.
|
|
124
|
+
|
|
125
|
+
First-account pairing prepares the file catalog before opening Files and adds
|
|
126
|
+
`Getting started with LePan.txt` once. The guide can be renamed or deleted and is
|
|
127
|
+
not duplicated when another phone joins. First setup also grants each account
|
|
128
|
+
write access only to its own node staging directory when Leither requires it.
|
|
129
|
+
|
|
115
130
|
An existing installation is backed up before replacement. The explicit `--upgrade` path requires the saved application and key-auth owner state before changing files, synchronizes the same published application MID, and does not rerun device or domain setup. This release intentionally does not migrate the earlier password-owner prototype. Application files are active only after Leither advances the application from `cur` to `last`; a publication timeout leaves the prior `last` version serving users.
|
|
116
131
|
|
|
117
132
|
Source code and design documentation are maintained separately. No device key, identity bundle, PPT, publisher key, or node-specific application MID is included in these release assets.
|
package/USER_MANUAL.md
CHANGED
|
@@ -142,8 +142,7 @@ This keeps what step 2.1 installed and adds users and phones:
|
|
|
142
142
|
|
|
143
143
|
1. Creates LifeDrive's private configuration in `<Leither root>/.lifedrive-household/`.
|
|
144
144
|
2. Installs and starts the identity service: `lifedrive-identity` through systemd on Linux, `uk.inoku.lifedrive-identity` through launchd on macOS, or `LifeDrive Identity` through Task Scheduler on Windows. Leither itself is not restarted and must be running separately.
|
|
145
|
-
3.
|
|
146
|
-
*"Keep the invitation above private. It expires in ten minutes."*
|
|
145
|
+
3. Displays a **setup invitation** as a QR code. If the terminal is too small, the full-size QR image opens automatically on this computer. The invitation expires in ten minutes.
|
|
147
146
|
|
|
148
147
|
The setup invitation is what makes a phone the first user of this node. Treat it
|
|
149
148
|
like a key: do not post it, email it to others, or paste it anywhere public.
|
|
@@ -152,13 +151,16 @@ like a key: do not post it, email it to others, or paste it anywhere public.
|
|
|
152
151
|
|
|
153
152
|
Within ten minutes of the invitation being printed:
|
|
154
153
|
|
|
155
|
-
1.
|
|
154
|
+
1. Scan the installer’s final QR code or the QR image that opens automatically. The saved image path is a fallback for remote sessions or computers without an image viewer. If you used the standalone shell installer, copy the whole invitation block instead.
|
|
156
155
|
2. Open LifeDrive on the phone. The **Set up your LifeDrive** screen opens by itself (or open **Settings → Set up users**).
|
|
157
156
|
3. Enter **Your name** and a name for this device.
|
|
158
157
|
4. Tap **Scan QR code** and point the phone at the terminal or saved image. You can also use **Paste node identity** or **Choose identity file**.
|
|
159
158
|
|
|
160
|
-
The phone creates its own device key, claims the node, and opens your
|
|
161
|
-
|
|
159
|
+
The phone creates its own device key, claims the node, and opens your personal
|
|
160
|
+
drive after its file list is ready. Files contains **Getting started with LePan.txt**,
|
|
161
|
+
a short guide to Files, Backups, connecting other phones, and keeping access to
|
|
162
|
+
your account. It is added once per account; reconnecting a phone does not duplicate
|
|
163
|
+
it, and deleting or renaming it does not cause it to return. You are now the node's first user and its **administrator**, and
|
|
162
164
|
this phone is a **device manager**.
|
|
163
165
|
|
|
164
166
|
You can close the setup screen without pairing to look around the app. Tapping an
|
|
@@ -168,7 +170,7 @@ empty page, or **Settings → Set up users**, opens it again.
|
|
|
168
170
|
|
|
169
171
|
| Situation | What to do |
|
|
170
172
|
|---|---|
|
|
171
|
-
| The invitation expired before you pasted it | On the node,
|
|
173
|
+
| The invitation expired before you pasted it | On the node, run `npx --yes @inoku/lepan@latest --household` again for a fresh QR code. Setup renews an unclaimed invitation and preserves the existing identity; no manual service commands are needed. |
|
|
172
174
|
| You pasted it, but the app lost its connection or was closed | Open the app on **the same phone** and paste **the same invitation** again. A claim that has started can finish after the ten minutes have passed. Do not delete the app or ask for a new invitation: that would abandon the phone's pending key. |
|
|
173
175
|
| Setup says the node already has users | The node has been claimed. Add further devices from **My devices** (section 4), not with a new setup invitation. |
|
|
174
176
|
|
|
@@ -361,12 +363,26 @@ What remains true:
|
|
|
361
363
|
- **Other users are unaffected.** Their drives and devices keep working.
|
|
362
364
|
- **Recovery needs the node operator.** Contact whoever runs the node.
|
|
363
365
|
|
|
364
|
-
For node operators:
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
366
|
+
For node operators: run this on the computer hosting Leither, replacing `Owner`
|
|
367
|
+
with the existing account name (quote names containing spaces), or its exact user
|
|
368
|
+
ID if names are duplicated:
|
|
369
|
+
|
|
370
|
+
```bash
|
|
371
|
+
npx --yes @inoku/lepan@latest --recover-device Owner
|
|
372
|
+
```
|
|
373
|
+
|
|
374
|
+
The account service briefly stops to issue a private reconnect invitation, then
|
|
375
|
+
starts again before the QR code is shown. Scan it under **Settings → Set up users**
|
|
376
|
+
on the phone. It enrolls a new device manager into the same account; account keys,
|
|
377
|
+
Files, Backups, and other devices are preserved. A reconnect invitation expires
|
|
378
|
+
in ten minutes unless that phone has already begun claiming it. Treat it as a
|
|
379
|
+
private account-access key. An expired, unclaimed code can be replaced by rerunning
|
|
380
|
+
the same command. Once connected, remove access for the forgotten device from
|
|
381
|
+
**My devices**. Leither itself stays running.
|
|
382
|
+
|
|
383
|
+
The node operator's local access authorizes this recovery; ordinary device
|
|
384
|
+
invitations still require approval from a paired device manager. `--household`
|
|
385
|
+
remains first-account setup and cannot replace an existing account.
|
|
370
386
|
|
|
371
387
|
### 5.4 Prevent lockout
|
|
372
388
|
|
package/bin/lifedrive.js
CHANGED
|
@@ -12,12 +12,37 @@ const distributionDirectory = path.resolve(__dirname, "..", "dist");
|
|
|
12
12
|
const bundlePath = path.join(distributionDirectory, "lifedrive-bundle.tar.gz");
|
|
13
13
|
const checksumPath = `${bundlePath}.sha256`;
|
|
14
14
|
|
|
15
|
+
function openPairingImage(imagePath) {
|
|
16
|
+
// A remote server must not open a window in another user's desktop session.
|
|
17
|
+
if (process.env.SSH_CONNECTION || process.env.SSH_TTY) return false;
|
|
18
|
+
let command;
|
|
19
|
+
let args;
|
|
20
|
+
if (process.platform === "darwin") {
|
|
21
|
+
command = "/usr/bin/open";
|
|
22
|
+
args = [imagePath];
|
|
23
|
+
} else if (process.platform === "win32") {
|
|
24
|
+
command = "powershell.exe";
|
|
25
|
+
args = ["-NoLogo", "-NoProfile", "-NonInteractive", "-Command",
|
|
26
|
+
"Start-Process -FilePath $env:LEPAN_PAIRING_IMAGE -ErrorAction Stop"];
|
|
27
|
+
} else if (process.platform === "linux" && (process.env.DISPLAY || process.env.WAYLAND_DISPLAY)) {
|
|
28
|
+
command = "xdg-open";
|
|
29
|
+
args = [imagePath];
|
|
30
|
+
} else {
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
33
|
+
const result = spawnSync(command, args, {
|
|
34
|
+
stdio: "ignore", timeout: 5000,
|
|
35
|
+
env: { ...process.env, LEPAN_PAIRING_IMAGE: imagePath },
|
|
36
|
+
});
|
|
37
|
+
return !result.error && result.status === 0;
|
|
38
|
+
}
|
|
39
|
+
|
|
15
40
|
async function showPairingCode(resultPath) {
|
|
16
41
|
if (!fs.existsSync(resultPath)) return;
|
|
17
42
|
// The child writes this only after setup succeeds. Never scrape its output:
|
|
18
43
|
// it can contain node keys as well as the mobile device's pairing identity.
|
|
19
44
|
const pairing = JSON.parse(fs.readFileSync(resultPath, "utf8"));
|
|
20
|
-
if (pairing.version !== 1 || !["lifedrive-device-identity", "lifedrive-node-setup"].includes(pairing.type)) {
|
|
45
|
+
if (pairing.version !== 1 || !["lifedrive-device-identity", "lifedrive-node-setup", "lifedrive-user-identity"].includes(pairing.type)) {
|
|
21
46
|
throw new Error("Unsupported pairing data");
|
|
22
47
|
}
|
|
23
48
|
const directory = fs.readFileSync(`${resultPath}.directory`, "utf8");
|
|
@@ -27,7 +52,7 @@ async function showPairingCode(resultPath) {
|
|
|
27
52
|
// The node enforces expiry and returns account details after a successful claim.
|
|
28
53
|
// Keep the full invitation in the import file, and leave legacy identities intact.
|
|
29
54
|
// iOS still requires certificate_sha256 even when Leither transport uses a key.
|
|
30
|
-
const qrPayload = pairing.type
|
|
55
|
+
const qrPayload = pairing.type !== "lifedrive-device-identity"
|
|
31
56
|
? JSON.stringify(Object.fromEntries([
|
|
32
57
|
"type", "version", "app_id", "node_id", "endpoint", "transport",
|
|
33
58
|
"transport_key", "certificate_sha256", "request_id", "secret",
|
|
@@ -40,12 +65,12 @@ async function showPairingCode(resultPath) {
|
|
|
40
65
|
// Keep a private copy even when QR generation succeeds.
|
|
41
66
|
fs.writeFileSync(identityPath, payload, { flag: "wx", mode: 0o600 });
|
|
42
67
|
const options = { errorCorrectionLevel: "M", margin: 4, scale: 8 };
|
|
43
|
-
const privacyNote = pairing.type
|
|
68
|
+
const privacyNote = pairing.type !== "lifedrive-device-identity"
|
|
44
69
|
? "Keep it private. This invitation expires ten minutes after creation."
|
|
45
70
|
: "This contains your device private key. Keep it private and delete it after pairing.";
|
|
46
71
|
const renewalHint = pairing.type === "lifedrive-node-setup"
|
|
47
72
|
? "\nInvitation expired? Run this again on the node:\n npx --yes @inoku/lepan@latest --household\n"
|
|
48
|
-
: "";
|
|
73
|
+
: pairing.type === "lifedrive-user-identity" ? "\nInvitation expired? Run the same reconnect command again on this computer.\n" : "";
|
|
49
74
|
let modules;
|
|
50
75
|
try {
|
|
51
76
|
const QRCode = require("qrcode");
|
|
@@ -64,17 +89,27 @@ async function showPairingCode(resultPath) {
|
|
|
64
89
|
process.stderr.write(renewalHint);
|
|
65
90
|
return;
|
|
66
91
|
}
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
// Small terminal codes use half-height blocks. If the terminal would wrap,
|
|
71
|
-
// or scroll the instructions out of view, use the full-resolution PNG.
|
|
92
|
+
// Never hide a terminal code just because the window is short. Open the PNG
|
|
93
|
+
// automatically when the whole code cannot be visible at once, and put the
|
|
94
|
+
// terminal code last so subsequent instructions cannot scroll it away.
|
|
72
95
|
const width = modules.size + options.margin * 2;
|
|
73
96
|
const height = Math.ceil(width / 2);
|
|
74
|
-
const
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
97
|
+
const fitsWidth = process.stdout.isTTY && process.stdout.columns > width;
|
|
98
|
+
const fitsScreen = fitsWidth && process.stdout.rows >= height + 3;
|
|
99
|
+
const imageOpened = !fitsScreen && openPairingImage(imagePath);
|
|
100
|
+
process.stdout.write("\nPair your phone\n\n");
|
|
101
|
+
process.stdout.write("Open LePan > Settings > Set up users > Scan QR code.\n");
|
|
102
|
+
process.stdout.write(imageOpened
|
|
103
|
+
? "The QR image has opened automatically. Scan it with your phone.\n"
|
|
104
|
+
: fitsWidth ? "Scan the QR code below with your phone.\n"
|
|
105
|
+
: "This terminal is too narrow for the QR code and no image viewer could be opened. Open the saved image below.\n");
|
|
106
|
+
process.stdout.write(`${privacyNote}\n`);
|
|
107
|
+
process.stdout.write(`\nSaved QR image: ${imagePath}\n`);
|
|
108
|
+
process.stdout.write(`Pairing file (Choose identity file): ${identityPath}\n`);
|
|
109
|
+
process.stdout.write("Keep this computer on and connected while using LePan.\n");
|
|
110
|
+
process.stdout.write(renewalHint);
|
|
111
|
+
if (fitsWidth) {
|
|
112
|
+
process.stdout.write("\n");
|
|
78
113
|
// Explicit colors and a four-module quiet zone work on light/dark themes.
|
|
79
114
|
const dark = (x, y) => x >= 0 && y >= 0 && x < modules.size && y < modules.size && modules.get(y, x);
|
|
80
115
|
let terminal = "";
|
|
@@ -86,16 +121,7 @@ async function showPairingCode(resultPath) {
|
|
|
86
121
|
terminal += "\x1b[0m\n";
|
|
87
122
|
}
|
|
88
123
|
process.stdout.write(terminal);
|
|
89
|
-
} else {
|
|
90
|
-
process.stdout.write(" 3. Open the saved QR image on this computer and scan it.\n");
|
|
91
124
|
}
|
|
92
|
-
process.stdout.write(`\nQR image:\n ${imagePath}\n\n${privacyNote}\n`);
|
|
93
|
-
process.stdout.write("\nNo Scan QR code button? Transfer this pairing file to your phone:\n");
|
|
94
|
-
process.stdout.write(` ${identityPath}\n`);
|
|
95
|
-
process.stdout.write("Then open Settings > Set up users > Choose identity file.\n");
|
|
96
|
-
process.stdout.write("Keep the pairing file private; delete the transfer copy after import.\n");
|
|
97
|
-
process.stdout.write("Keep this computer on and connected while using LePan.\n");
|
|
98
|
-
process.stdout.write(renewalHint);
|
|
99
125
|
}
|
|
100
126
|
|
|
101
127
|
async function runInstaller(command, args) {
|
|
@@ -127,6 +153,7 @@ function windowsArguments(values) {
|
|
|
127
153
|
const valueOptions = new Map([
|
|
128
154
|
["--leither-root", "-LeitherRoot"],
|
|
129
155
|
["--storage-max-gb", "-StorageMaxGB"],
|
|
156
|
+
["--recover-device", "-RecoverDevice"],
|
|
130
157
|
]);
|
|
131
158
|
const switches = new Map([
|
|
132
159
|
["--no-install-leither", "-NoInstallLeither"],
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
[diffend] Oversized file quarantined before diffing.
|
|
2
2
|
name: package/dist/lifedrive-bundle.tar.gz
|
|
3
|
-
size:
|
|
4
|
-
sha256:
|
|
3
|
+
size: 44204388 bytes
|
|
4
|
+
sha256: b1d6c652dbda51b836a30778abb722774fd28559373cee7efe2670991d7297b7
|
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
b1d6c652dbda51b836a30778abb722774fd28559373cee7efe2670991d7297b7 lifedrive-bundle.tar.gz
|
|
@@ -8,6 +8,7 @@ param(
|
|
|
8
8
|
[switch]$LeitherService,
|
|
9
9
|
[switch]$Upgrade,
|
|
10
10
|
[switch]$Household,
|
|
11
|
+
[string]$RecoverDevice,
|
|
11
12
|
[switch]$Help
|
|
12
13
|
)
|
|
13
14
|
|
|
@@ -28,6 +29,7 @@ Windows options:
|
|
|
28
29
|
--leither-service Configure Leither startup only.
|
|
29
30
|
--upgrade Upgrade an existing Windows LePan installation.
|
|
30
31
|
--household Set up household users or renew an unclaimed setup invitation.
|
|
32
|
+
--recover-device USER Reconnect a phone to an existing account name or user ID.
|
|
31
33
|
|
|
32
34
|
Run Windows Terminal or PowerShell as Administrator. Windows setup supports
|
|
33
35
|
native x64 Windows 10/11 and Windows Server; WSL and Git Bash are not required.
|
|
@@ -35,6 +37,10 @@ native x64 Windows 10/11 and Windows Server; WSL and Git Bash are not required.
|
|
|
35
37
|
}
|
|
36
38
|
|
|
37
39
|
if ($Help) { Show-Usage; return }
|
|
40
|
+
if ($RecoverDevice) {
|
|
41
|
+
if ($Upgrade -or $LeitherService) { throw "Use --recover-device separately from --upgrade and --leither-service." }
|
|
42
|
+
$Household = $true
|
|
43
|
+
}
|
|
38
44
|
if ($Upgrade -and $LeitherService) { throw "Use -Upgrade and -LeitherService separately." }
|
|
39
45
|
if ($StorageMaxGB -lt 0) { throw "Leither storage must be a positive whole number of gigabytes." }
|
|
40
46
|
if ($StorageMaxGB -eq 0 -and $env:LIFEDRIVE_STORAGE_MAX_GB) {
|
|
@@ -469,7 +475,7 @@ if ($Upgrade) {
|
|
|
469
475
|
return
|
|
470
476
|
}
|
|
471
477
|
try {
|
|
472
|
-
& (Join-Path $root "lifedrive-identity\setup-node.ps1") -LeitherRoot $root
|
|
478
|
+
& (Join-Path $root "lifedrive-identity\setup-node.ps1") -LeitherRoot $root -RecoverDevice $RecoverDevice
|
|
473
479
|
} catch {
|
|
474
480
|
if ($identityTaskStopped) {
|
|
475
481
|
try { Start-ScheduledTask -TaskName $identityTaskName } catch {}
|
|
@@ -12,6 +12,7 @@ LEITHER_SERVICE_ONLY=0
|
|
|
12
12
|
LEITHER_SERVICE_BOOTSTRAPPED=0
|
|
13
13
|
HOUSEHOLD_CONFIG=""
|
|
14
14
|
HOUSEHOLD_SETUP=0
|
|
15
|
+
RECOVER_DEVICE=""
|
|
15
16
|
STORAGE_MAX_GB="${LIFEDRIVE_STORAGE_MAX_GB:-}"
|
|
16
17
|
setup_command_args=()
|
|
17
18
|
setup_arg_count=0
|
|
@@ -29,6 +30,7 @@ Installer options:
|
|
|
29
30
|
--release-base URL Alternate GitHub Release asset base URL.
|
|
30
31
|
--upgrade Upgrade an existing LePan without changing device authorization.
|
|
31
32
|
--household Set up household users or renew an unclaimed setup invitation.
|
|
33
|
+
--recover-device USER Reconnect a phone to an existing account, using its name or user ID.
|
|
32
34
|
--household-config FILE Install mobile-led household setup using a private service configuration.
|
|
33
35
|
|
|
34
36
|
Setup options are forwarded to lifeDrive-setup.sh. Common examples:
|
|
@@ -53,6 +55,12 @@ while (( $# )); do
|
|
|
53
55
|
--household)
|
|
54
56
|
HOUSEHOLD_SETUP=1
|
|
55
57
|
;;
|
|
58
|
+
--recover-device)
|
|
59
|
+
shift
|
|
60
|
+
[[ $# -gt 0 && -n "$1" && "$1" != --* ]] || { echo "--recover-device requires an existing account name or user ID" >&2; exit 2; }
|
|
61
|
+
RECOVER_DEVICE="$1"
|
|
62
|
+
HOUSEHOLD_SETUP=1
|
|
63
|
+
;;
|
|
56
64
|
--household-config)
|
|
57
65
|
shift
|
|
58
66
|
[[ $# -gt 0 && -f "$1" ]] || { echo "--household-config requires a configuration file" >&2; exit 2; }
|
|
@@ -103,6 +111,10 @@ while (( $# )); do
|
|
|
103
111
|
shift
|
|
104
112
|
done
|
|
105
113
|
|
|
114
|
+
if [[ -n "$RECOVER_DEVICE" ]] && (( operation_count )); then
|
|
115
|
+
echo "Use --recover-device separately from --upgrade and device-management options." >&2
|
|
116
|
+
exit 2
|
|
117
|
+
fi
|
|
106
118
|
if (( operation_count > 1 )); then
|
|
107
119
|
echo "Choose only one of --upgrade, --add-device, --list-devices, or --revoke-device." >&2
|
|
108
120
|
exit 2
|
|
@@ -942,7 +954,7 @@ chmod 700 "$LEITHER_WORKDIR/lifeDrive/"*.sh
|
|
|
942
954
|
export LIFEDRIVE_WORKDIR="$LEITHER_WORKDIR"
|
|
943
955
|
export LIFEDRIVE_LEITHER_PATH="$LEITHER_WORKDIR/Leither"
|
|
944
956
|
if (( HOUSEHOLD_SETUP )); then
|
|
945
|
-
/bin/bash "$LEITHER_WORKDIR/lifedrive-identity/setup-node.sh" "$LEITHER_WORKDIR"
|
|
957
|
+
/bin/bash "$LEITHER_WORKDIR/lifedrive-identity/setup-node.sh" "$LEITHER_WORKDIR" "$RECOVER_DEVICE"
|
|
946
958
|
exit 0
|
|
947
959
|
fi
|
|
948
960
|
if [[ -n "$HOUSEHOLD_CONFIG" ]]; then
|