@cocorograph/hub-agent 0.6.72 → 0.6.74
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/package.json +1 -1
- package/scripts/install.ps1 +186 -121
- package/scripts/install.sh +4 -1
package/package.json
CHANGED
package/scripts/install.ps1
CHANGED
|
@@ -1,87 +1,109 @@
|
|
|
1
1
|
# =============================================================================
|
|
2
|
-
# hub-agent Windows
|
|
2
|
+
# hub-agent Windows one-liner installer (WSL2 method)
|
|
3
3
|
#
|
|
4
|
-
# Hub UI
|
|
5
|
-
#
|
|
4
|
+
# The Hub UI shows a PowerShell one-liner with the enrollment token + hub url
|
|
5
|
+
# embedded. The user pastes it into an ADMINISTRATOR PowerShell. This is the
|
|
6
|
+
# Windows counterpart of the bash install.sh.
|
|
6
7
|
#
|
|
7
|
-
#
|
|
8
|
-
#
|
|
8
|
+
# IMPORTANT: This script is intentionally ASCII-only. Windows PowerShell 5.1
|
|
9
|
+
# fetches the script with `irm` and runs it with `iex`; when the HTTP response
|
|
10
|
+
# has no charset, 5.1 decodes UTF-8 bytes using the legacy code page (e.g.
|
|
11
|
+
# CP932 on Japanese Windows), which turns any non-ASCII text into mojibake and
|
|
12
|
+
# can break parsing. Keeping everything ASCII avoids that entirely.
|
|
9
13
|
#
|
|
10
|
-
#
|
|
14
|
+
# Design doc: D00000_hub-agent/docs/windows-installer-design.md
|
|
15
|
+
#
|
|
16
|
+
# Standalone (no token):
|
|
11
17
|
# irm https://unpkg.com/@cocorograph/hub-agent@latest/scripts/install.ps1 | iex
|
|
12
18
|
#
|
|
13
|
-
# Hub UI
|
|
19
|
+
# Form generated by the Hub UI (token/url embedded):
|
|
14
20
|
# $env:HUB_AGENT_TOKEN="<tok>"; $env:HUB_AGENT_URL="https://api.hub.cocorograph.com"; `
|
|
15
21
|
# irm https://unpkg.com/@cocorograph/hub-agent@latest/scripts/install.ps1 | iex
|
|
16
22
|
#
|
|
17
|
-
#
|
|
18
|
-
#
|
|
19
|
-
#
|
|
20
|
-
#
|
|
21
|
-
#
|
|
23
|
+
# Flow:
|
|
24
|
+
# Phase 1: install WSL2 (admin required; reboot bridged via RunOnce)
|
|
25
|
+
# After reboot: create the first Ubuntu user unattended
|
|
26
|
+
# (cloud-init first, root-install + useradd as fallback)
|
|
27
|
+
# Phase 2: run the existing install.sh inside WSL
|
|
28
|
+
# (tmux/node/hub-agent/claude/enroll/install-service)
|
|
29
|
+
# Autostart: a Task Scheduler logon task wakes the distro so its systemd
|
|
30
|
+
# brings hub-agent up.
|
|
22
31
|
# =============================================================================
|
|
23
32
|
|
|
24
33
|
#Requires -Version 5.1
|
|
25
34
|
$ErrorActionPreference = "Stop"
|
|
26
35
|
|
|
27
|
-
# ---
|
|
28
|
-
# distro
|
|
29
|
-
|
|
30
|
-
$
|
|
31
|
-
$
|
|
32
|
-
$
|
|
33
|
-
$
|
|
34
|
-
$
|
|
35
|
-
$
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
$
|
|
40
|
-
$
|
|
41
|
-
|
|
42
|
-
|
|
36
|
+
# --- constants --------------------------------------------------------------
|
|
37
|
+
# Preferred distro is the LTS. We try this first, then a couple of fallbacks
|
|
38
|
+
# (older Windows 10 WSL catalogs may not know "Ubuntu-24.04").
|
|
39
|
+
$PREFERRED_DISTRO = "Ubuntu-24.04"
|
|
40
|
+
$DISTRO_CANDIDATES = @("Ubuntu-24.04", "Ubuntu")
|
|
41
|
+
$INSTALL_SH = "https://unpkg.com/@cocorograph/hub-agent@latest/scripts/install.sh"
|
|
42
|
+
$PS1_URL = "https://unpkg.com/@cocorograph/hub-agent@latest/scripts/install.ps1"
|
|
43
|
+
$RUNONCE_NAME = "HubAgentSetup"
|
|
44
|
+
$TASK_NAME = "HubAgentWSLBoot"
|
|
45
|
+
$DEFAULT_HUB = "https://api.hub.cocorograph.com"
|
|
46
|
+
|
|
47
|
+
# --- params from env --------------------------------------------------------
|
|
48
|
+
$Token = $env:HUB_AGENT_TOKEN
|
|
49
|
+
$HubUrl = if ($env:HUB_AGENT_URL) { $env:HUB_AGENT_URL } else { $DEFAULT_HUB }
|
|
50
|
+
$IsResume = ($env:HUB_AGENT_RESUME -eq "1") # set by RunOnce after reboot
|
|
51
|
+
|
|
52
|
+
# --- colored logging (ASCII only) ------------------------------------------
|
|
43
53
|
function Write-Step($m) { Write-Host "==> $m" -ForegroundColor Cyan }
|
|
44
54
|
function Write-Ok($m) { Write-Host "[OK] $m" -ForegroundColor Green }
|
|
45
55
|
function Write-Warn($m) { Write-Host "[!] $m" -ForegroundColor Yellow }
|
|
46
56
|
function Write-Err($m) { Write-Host "[x] $m" -ForegroundColor Red }
|
|
47
57
|
|
|
48
|
-
# ---
|
|
58
|
+
# --- helpers ----------------------------------------------------------------
|
|
49
59
|
function Test-IsAdmin {
|
|
50
60
|
$id = [Security.Principal.WindowsIdentity]::GetCurrent()
|
|
51
61
|
$pr = New-Object Security.Principal.WindowsPrincipal($id)
|
|
52
62
|
return $pr.IsInRole([Security.Principal.WindowsBuiltinRole]::Administrator)
|
|
53
63
|
}
|
|
54
64
|
|
|
55
|
-
# wsl -l -q
|
|
65
|
+
# `wsl -l -q` prints UTF-16LE with stray NULs; sanitize and split to an array.
|
|
56
66
|
function Get-WslDistros {
|
|
57
67
|
try {
|
|
58
68
|
$raw = (wsl.exe -l -q) 2>$null
|
|
59
69
|
if (-not $raw) { return @() }
|
|
60
|
-
return ($raw -replace "`0", "") -split "`r?`n" |
|
|
70
|
+
return ($raw -replace "`0", "") -split "`r?`n" |
|
|
71
|
+
ForEach-Object { $_.Trim() } | Where-Object { $_ -ne "" }
|
|
61
72
|
} catch { return @() }
|
|
62
73
|
}
|
|
63
74
|
|
|
64
|
-
|
|
75
|
+
# Return the name of an installed Ubuntu distro (prefer 24.04), or $null.
|
|
76
|
+
function Resolve-InstalledUbuntu {
|
|
77
|
+
$installed = Get-WslDistros
|
|
78
|
+
foreach ($cand in $DISTRO_CANDIDATES) {
|
|
79
|
+
if ($installed -contains $cand) { return $cand }
|
|
80
|
+
}
|
|
81
|
+
# any distro whose name starts with "Ubuntu"
|
|
82
|
+
$u = $installed | Where-Object { $_ -like "Ubuntu*" } | Select-Object -First 1
|
|
83
|
+
if ($u) { return $u }
|
|
84
|
+
return $null
|
|
85
|
+
}
|
|
65
86
|
|
|
66
|
-
# WSL
|
|
87
|
+
# Is the WSL engine (kernel + platform) usable at all?
|
|
67
88
|
function Test-WslReady {
|
|
68
89
|
try { wsl.exe --status *> $null; return ($LASTEXITCODE -eq 0) } catch { return $false }
|
|
69
90
|
}
|
|
70
91
|
|
|
71
|
-
# distro
|
|
72
|
-
function Test-WslUserReady($user) {
|
|
73
|
-
if (-not $user) { return $false }
|
|
74
|
-
try { wsl.exe -d $
|
|
92
|
+
# Does user exist inside the given distro? (idempotency check)
|
|
93
|
+
function Test-WslUserReady($distro, $user) {
|
|
94
|
+
if (-not $distro -or -not $user) { return $false }
|
|
95
|
+
try { wsl.exe -d $distro -u root -- id $user *> $null; return ($LASTEXITCODE -eq 0) }
|
|
96
|
+
catch { return $false }
|
|
75
97
|
}
|
|
76
98
|
|
|
77
|
-
# Windows
|
|
99
|
+
# Sanitize Windows username to a valid Linux name ([a-z_][a-z0-9_-]*).
|
|
78
100
|
function Get-LinuxUserName {
|
|
79
101
|
$u = ($env:USERNAME).ToLower() -replace '[^a-z0-9_-]', ''
|
|
80
102
|
if ($u -eq '' -or $u -match '^[0-9]') { $u = "hub$u" }
|
|
81
103
|
return $u
|
|
82
104
|
}
|
|
83
105
|
|
|
84
|
-
#
|
|
106
|
+
# Register "re-run myself with RESUME=1 after reboot", carrying token/url.
|
|
85
107
|
function Set-ResumeOnReboot {
|
|
86
108
|
$cmd = "powershell -NoProfile -ExecutionPolicy Bypass -Command " +
|
|
87
109
|
"`"`$env:HUB_AGENT_TOKEN='$Token'; `$env:HUB_AGENT_URL='$HubUrl'; " +
|
|
@@ -90,21 +112,20 @@ function Set-ResumeOnReboot {
|
|
|
90
112
|
-Name $RUNONCE_NAME -Value $cmd
|
|
91
113
|
}
|
|
92
114
|
|
|
93
|
-
#
|
|
94
|
-
|
|
115
|
+
# Leave the reboot decision to the user (auto-reboot risks unsaved work).
|
|
116
|
+
# RunOnce is already registered, so "later" still auto-resumes on next boot.
|
|
117
|
+
function Invoke-RebootPrompt {
|
|
95
118
|
Write-Host ""
|
|
96
|
-
Write-Step "WSL2
|
|
97
|
-
Write-Host "
|
|
98
|
-
$ans = Read-Host "
|
|
99
|
-
if ($ans -match '^[Yy]') {
|
|
100
|
-
|
|
101
|
-
} else {
|
|
102
|
-
Write-Warn "あとで Windows を再起動すると、セットアップが自動で続きます。"
|
|
103
|
-
}
|
|
119
|
+
Write-Step "WSL2 is installed. A Windows reboot is required to continue."
|
|
120
|
+
Write-Host " After reboot, setup resumes automatically (no manual steps)." -ForegroundColor Cyan
|
|
121
|
+
$ans = Read-Host "Reboot now? [Y = reboot now / N = I'll reboot later]"
|
|
122
|
+
if ($ans -match '^[Yy]') { Restart-Computer }
|
|
123
|
+
else { Write-Warn "Reboot Windows later and setup will continue automatically." }
|
|
104
124
|
}
|
|
105
125
|
|
|
106
|
-
# cloud-init
|
|
107
|
-
#
|
|
126
|
+
# Place cloud-init user-data BEFORE first boot. WSL applies it on first launch,
|
|
127
|
+
# skipping the interactive OOBE. The file name must match the registered distro
|
|
128
|
+
# name, so we write one file per candidate name to be safe.
|
|
108
129
|
function Write-CloudInit($user) {
|
|
109
130
|
$ciDir = Join-Path $env:USERPROFILE ".cloud-init"
|
|
110
131
|
New-Item -ItemType Directory -Force -Path $ciDir | Out-Null
|
|
@@ -124,35 +145,75 @@ write_files:
|
|
|
124
145
|
[boot]
|
|
125
146
|
systemd=true
|
|
126
147
|
"@
|
|
127
|
-
#
|
|
128
|
-
$
|
|
129
|
-
$
|
|
130
|
-
|
|
131
|
-
|
|
148
|
+
$yaml = $yaml -replace "`r`n", "`n" # cloud-init wants LF + UTF-8 (no BOM)
|
|
149
|
+
$enc = New-Object System.Text.UTF8Encoding($false)
|
|
150
|
+
foreach ($name in $DISTRO_CANDIDATES) {
|
|
151
|
+
$path = Join-Path $ciDir "$name.user-data"
|
|
152
|
+
[System.IO.File]::WriteAllText($path, $yaml, $enc)
|
|
153
|
+
}
|
|
154
|
+
Write-Ok "cloud-init user-data placed in $ciDir"
|
|
132
155
|
}
|
|
133
156
|
|
|
134
|
-
#
|
|
135
|
-
|
|
136
|
-
|
|
157
|
+
# Update the WSL engine + online distro catalog. On Windows 10 the inbox WSL
|
|
158
|
+
# catalog is often stale and does not know Ubuntu-24.04; `wsl --update` pulls
|
|
159
|
+
# the Store WSL which refreshes the catalog. Failures are non-fatal (warn).
|
|
160
|
+
function Update-WslEngine {
|
|
161
|
+
Write-Step "Updating WSL engine (wsl --update)"
|
|
137
162
|
try {
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
return $false
|
|
143
|
-
}
|
|
144
|
-
return (Test-WslUserReady $user)
|
|
163
|
+
wsl.exe --update *> $null
|
|
164
|
+
if ($LASTEXITCODE -ne 0) { Write-Warn "wsl --update returned $LASTEXITCODE (continuing)" }
|
|
165
|
+
else { Write-Ok "WSL engine updated" }
|
|
166
|
+
} catch { Write-Warn "wsl --update failed (continuing)" }
|
|
145
167
|
}
|
|
146
168
|
|
|
147
|
-
#
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
169
|
+
# Install a distro without launching it. Tries candidate names and a no-flag
|
|
170
|
+
# fallback (older WSL may not support --no-launch). Returns the installed name
|
|
171
|
+
# or throws with actionable guidance.
|
|
172
|
+
function Install-Distro {
|
|
173
|
+
$existing = Resolve-InstalledUbuntu
|
|
174
|
+
if ($existing) { Write-Ok "Ubuntu distro already installed: $existing"; return $existing }
|
|
175
|
+
|
|
176
|
+
Update-WslEngine
|
|
177
|
+
|
|
178
|
+
foreach ($name in $DISTRO_CANDIDATES) {
|
|
179
|
+
Write-Step "Installing distro: $name"
|
|
180
|
+
# 1) modern: --no-launch
|
|
181
|
+
wsl.exe --install -d $name --no-launch *> $null
|
|
182
|
+
if ($LASTEXITCODE -eq 0 -and (Get-WslDistros) -contains $name) { return $name }
|
|
183
|
+
# 2) older WSL may reject --no-launch; retry without it (still no OOBE
|
|
184
|
+
# because cloud-init is already staged).
|
|
185
|
+
wsl.exe --install -d $name *> $null
|
|
186
|
+
if ($LASTEXITCODE -eq 0 -and (Get-WslDistros) -contains $name) { return $name }
|
|
187
|
+
Write-Warn "Could not install '$name', trying next candidate..."
|
|
155
188
|
}
|
|
189
|
+
|
|
190
|
+
# If we get here every candidate failed.
|
|
191
|
+
Write-Err "Failed to install a WSL Ubuntu distro automatically."
|
|
192
|
+
Write-Host ""
|
|
193
|
+
Write-Host "Please run these in an ADMINISTRATOR PowerShell, then re-run this installer:" -ForegroundColor Yellow
|
|
194
|
+
Write-Host " wsl --update" -ForegroundColor Yellow
|
|
195
|
+
Write-Host " wsl --list --online # confirm an Ubuntu name is listed" -ForegroundColor Yellow
|
|
196
|
+
Write-Host " wsl --install -d Ubuntu-24.04 # or the Ubuntu name shown above" -ForegroundColor Yellow
|
|
197
|
+
Write-Host ""
|
|
198
|
+
Write-Host "Note: Windows 10 needs version 21H2+ and an up-to-date WSL." -ForegroundColor Yellow
|
|
199
|
+
throw "distro install failed"
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
# cloud-init path: wait for completion, return $true if the user got created.
|
|
203
|
+
function Invoke-CloudInitProvision($distro, $user) {
|
|
204
|
+
Write-Step "Creating first Ubuntu user unattended (cloud-init)"
|
|
205
|
+
try { wsl.exe -d $distro -u root -- cloud-init status --wait *> $null }
|
|
206
|
+
catch { Write-Warn "cloud-init status --wait failed (cloud-init may be unsupported)"; return $false }
|
|
207
|
+
return (Test-WslUserReady $distro $user)
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
# Fallback: launcher `install --root` then useradd. Launcher exe name depends
|
|
211
|
+
# on the distro (ubuntu2404.exe etc.); resolve it from the distro name.
|
|
212
|
+
function Invoke-RootInstallProvision($distro, $user) {
|
|
213
|
+
Write-Step "Creating first Ubuntu user unattended (root-install fallback)"
|
|
214
|
+
$launcher = ($distro.ToLower() -replace '[^a-z0-9]', '') + ".exe" # Ubuntu-24.04 -> ubuntu2404.exe
|
|
215
|
+
try { & $launcher install --root *> $null }
|
|
216
|
+
catch { Write-Warn "$launcher install --root failed (continuing to useradd)" }
|
|
156
217
|
$script = @"
|
|
157
218
|
set -e
|
|
158
219
|
useradd -m -s /bin/bash -G sudo '$user' 2>/dev/null || true
|
|
@@ -162,99 +223,103 @@ chmod 0440 /etc/sudoers.d/90-hub-$user
|
|
|
162
223
|
printf '[user]\ndefault=$user\n[boot]\nsystemd=true\n' > /etc/wsl.conf
|
|
163
224
|
"@
|
|
164
225
|
$script = $script -replace "`r`n", "`n"
|
|
165
|
-
wsl.exe -d $
|
|
226
|
+
wsl.exe -d $distro -u root -- bash -lc $script
|
|
166
227
|
wsl.exe --shutdown
|
|
167
|
-
return (Test-WslUserReady $user)
|
|
228
|
+
return (Test-WslUserReady $distro $user)
|
|
168
229
|
}
|
|
169
230
|
|
|
170
|
-
# distro
|
|
171
|
-
function
|
|
172
|
-
$has = (wsl.exe -d $
|
|
231
|
+
# Ensure systemd=true in the distro's /etc/wsl.conf (idempotent).
|
|
232
|
+
function Set-Systemd($distro) {
|
|
233
|
+
$has = (wsl.exe -d $distro -u root -- bash -lc "grep -q 'systemd=true' /etc/wsl.conf 2>/dev/null && echo yes || echo no")
|
|
173
234
|
if (($has -replace "`0","").Trim() -ne "yes") {
|
|
174
|
-
wsl.exe -d $
|
|
235
|
+
wsl.exe -d $distro -u root -- bash -lc "printf '[boot]\nsystemd=true\n' >> /etc/wsl.conf"
|
|
175
236
|
wsl.exe --shutdown
|
|
176
237
|
}
|
|
177
238
|
}
|
|
178
239
|
|
|
179
|
-
#
|
|
180
|
-
function Register-BootTask($user) {
|
|
181
|
-
Write-Step "
|
|
182
|
-
$action = New-ScheduledTaskAction -Execute "wsl.exe" -Argument "-d $
|
|
240
|
+
# Register a logon task that wakes the distro (its systemd starts hub-agent).
|
|
241
|
+
function Register-BootTask($distro, $user) {
|
|
242
|
+
Write-Step "Registering autostart on logon (Task Scheduler)"
|
|
243
|
+
$action = New-ScheduledTaskAction -Execute "wsl.exe" -Argument "-d $distro -u $user -- /bin/true"
|
|
183
244
|
$trigger = New-ScheduledTaskTrigger -AtLogOn
|
|
184
245
|
$set = New-ScheduledTaskSettingsSet -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries -StartWhenAvailable
|
|
185
246
|
Register-ScheduledTask -TaskName $TASK_NAME -Action $action -Trigger $trigger -Settings $set `
|
|
186
247
|
-RunLevel Limited -Force | Out-Null
|
|
187
|
-
Write-Ok "
|
|
248
|
+
Write-Ok "Logon task '$TASK_NAME' registered"
|
|
188
249
|
}
|
|
189
250
|
|
|
190
|
-
#
|
|
191
|
-
function Invoke-WslInstaller($user) {
|
|
192
|
-
Write-Step "
|
|
251
|
+
# Run the existing install.sh inside WSL.
|
|
252
|
+
function Invoke-WslInstaller($distro, $user) {
|
|
253
|
+
Write-Step "Setting up hub-agent inside WSL (existing install.sh)"
|
|
193
254
|
$tok = if ($Token) { $Token } else { "" }
|
|
194
255
|
$inner = "curl -fsSL '$INSTALL_SH' | HUB_AGENT_TOKEN='$tok' HUB_AGENT_URL='$HubUrl' bash"
|
|
195
|
-
wsl.exe -d $
|
|
196
|
-
if ($LASTEXITCODE -ne 0) { throw "
|
|
256
|
+
wsl.exe -d $distro -u $user -- bash -lc $inner
|
|
257
|
+
if ($LASTEXITCODE -ne 0) { throw "install.sh inside WSL failed (exit $LASTEXITCODE)" }
|
|
197
258
|
}
|
|
198
259
|
|
|
199
260
|
# =============================================================================
|
|
200
|
-
#
|
|
261
|
+
# main
|
|
201
262
|
# =============================================================================
|
|
202
263
|
function Main {
|
|
203
|
-
Write-Step "hub-agent Windows
|
|
264
|
+
Write-Step "Starting hub-agent Windows setup (WSL2 method)"
|
|
204
265
|
|
|
205
266
|
if (-not (Test-IsAdmin)) {
|
|
206
|
-
Write-Err "
|
|
267
|
+
Write-Err "Administrator privileges are required. Reopen PowerShell as Administrator."
|
|
207
268
|
exit 1
|
|
208
269
|
}
|
|
209
270
|
|
|
210
271
|
$user = Get-LinuxUserName
|
|
211
272
|
|
|
212
|
-
# ---
|
|
213
|
-
if (-not $IsResume -and
|
|
214
|
-
Write-Step "WSL2 +
|
|
215
|
-
Set-ResumeOnReboot
|
|
216
|
-
Write-CloudInit $user
|
|
217
|
-
|
|
218
|
-
|
|
273
|
+
# --- Phase 1: install WSL2 + distro (only when none present; bridges reboot) ---
|
|
274
|
+
if (-not $IsResume -and -not (Resolve-InstalledUbuntu)) {
|
|
275
|
+
Write-Step "Installing WSL2 + Ubuntu"
|
|
276
|
+
Set-ResumeOnReboot # arm auto-resume first
|
|
277
|
+
Write-CloudInit $user # stage cloud-init before first boot
|
|
278
|
+
$installed = Install-Distro # robust: update + candidate names + fallbacks
|
|
279
|
+
Write-Ok "Distro installed: $installed"
|
|
280
|
+
Invoke-RebootPrompt # reboot is the user's choice
|
|
219
281
|
return
|
|
220
282
|
}
|
|
221
283
|
|
|
222
|
-
# ---
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
284
|
+
# --- after reboot, or WSL already present: resolve the real distro name ---
|
|
285
|
+
$distro = Resolve-InstalledUbuntu
|
|
286
|
+
if (-not $distro) {
|
|
287
|
+
# RESUME but distro not visible yet: the deployment may still be unpacking.
|
|
288
|
+
Write-Warn "Ubuntu distro not found yet; attempting install..."
|
|
226
289
|
Write-CloudInit $user
|
|
290
|
+
$distro = Install-Distro
|
|
227
291
|
}
|
|
292
|
+
Write-Ok "Using distro: $distro"
|
|
228
293
|
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
if (-not (Test-Path (Join-Path $env:USERPROFILE ".cloud-init\$
|
|
294
|
+
# --- create the first Ubuntu user unattended ---
|
|
295
|
+
if (-not (Test-WslUserReady $distro $user)) {
|
|
296
|
+
if (-not (Test-Path (Join-Path $env:USERPROFILE ".cloud-init\$distro.user-data"))) {
|
|
232
297
|
Write-CloudInit $user
|
|
233
298
|
}
|
|
234
|
-
$ok = Invoke-CloudInitProvision $user
|
|
299
|
+
$ok = Invoke-CloudInitProvision $distro $user
|
|
235
300
|
if (-not $ok) {
|
|
236
|
-
Write-Warn "cloud-init
|
|
237
|
-
$ok = Invoke-RootInstallProvision $user
|
|
301
|
+
Write-Warn "cloud-init did not create the user; switching to root-install method."
|
|
302
|
+
$ok = Invoke-RootInstallProvision $distro $user
|
|
238
303
|
}
|
|
239
|
-
if (-not $ok) { throw "Ubuntu
|
|
240
|
-
Write-Ok "Ubuntu
|
|
304
|
+
if (-not $ok) { throw "Failed to create Ubuntu user '$user' unattended" }
|
|
305
|
+
Write-Ok "Created Ubuntu user '$user' (no password / NOPASSWD sudo)"
|
|
241
306
|
} else {
|
|
242
|
-
Write-Ok "Ubuntu
|
|
307
|
+
Write-Ok "Ubuntu user '$user' already exists"
|
|
243
308
|
}
|
|
244
309
|
|
|
245
|
-
|
|
310
|
+
Set-Systemd $distro
|
|
246
311
|
|
|
247
|
-
# ---
|
|
248
|
-
Invoke-WslInstaller $user
|
|
312
|
+
# --- Phase 2: run install.sh inside WSL ---
|
|
313
|
+
Invoke-WslInstaller $distro $user
|
|
249
314
|
|
|
250
|
-
# ---
|
|
251
|
-
Register-BootTask $user
|
|
315
|
+
# --- autostart ---
|
|
316
|
+
Register-BootTask $distro $user
|
|
252
317
|
|
|
253
318
|
Write-Host ""
|
|
254
|
-
Write-Ok "
|
|
319
|
+
Write-Ok "Setup complete. Check the online status in the Hub UI:"
|
|
255
320
|
Write-Host " https://hub.cocorograph.com/user/cockpit/agents" -ForegroundColor Cyan
|
|
256
|
-
Write-Warn "
|
|
257
|
-
Write-Warn "
|
|
321
|
+
Write-Warn "Keep your working repos INSIDE WSL (e.g. /home/$user/...)."
|
|
322
|
+
Write-Warn "Windows drives (/mnt/c/...) have unreliable file watching."
|
|
258
323
|
}
|
|
259
324
|
|
|
260
325
|
Main
|
package/scripts/install.sh
CHANGED
|
@@ -483,7 +483,10 @@ _install_node_lts_brew() {
|
|
|
483
483
|
# - 範囲超過(current 系等) → LTS にダウングレード
|
|
484
484
|
ensure_node_version() {
|
|
485
485
|
local v
|
|
486
|
-
|
|
486
|
+
# node 皆無のクリーン環境では `node --version` が exit 127。set -euo pipefail 下
|
|
487
|
+
# では pipefail がこれを拾ってスクリプトごと死ぬため、`|| v=""` で必ず吸収する
|
|
488
|
+
# (macOS テスト機には既に node があり露見しなかった潜在バグ。WSL クリーン Ubuntu で発覚)。
|
|
489
|
+
v=$(node --version 2>/dev/null | sed 's/^v//' | cut -d. -f1) || v=""
|
|
487
490
|
if [[ -z "$v" ]]; then
|
|
488
491
|
color_step "node が未インストール → $NODE_DEFAULT_BREW_FORMULA (Active LTS) を install"
|
|
489
492
|
if [[ "$(uname)" == "Darwin" ]]; then
|