ework-aio 0.1.12 → 0.1.14
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/bin/install.sh +83 -5
- package/package.json +1 -1
package/bin/install.sh
CHANGED
|
@@ -38,6 +38,8 @@ BOT_NAME="ework-daemon"
|
|
|
38
38
|
NO_START=0
|
|
39
39
|
ASSUME_YES=0
|
|
40
40
|
NO_RESTART=0
|
|
41
|
+
AS_USER=""
|
|
42
|
+
ALLOW_ROOT=0
|
|
41
43
|
CFG_ARGS=()
|
|
42
44
|
MODE_ARGS=()
|
|
43
45
|
|
|
@@ -67,6 +69,10 @@ Install options:
|
|
|
67
69
|
--bot-name <login> Bot username (default: ework-daemon)
|
|
68
70
|
--no-start Install units but don't start services
|
|
69
71
|
--yes Skip all prompts (use generated defaults)
|
|
72
|
+
--as-user <login> (sudo only) drop priv: re-exec install as <login>
|
|
73
|
+
after enabling linger. Data + opencode + npm
|
|
74
|
+
resolved under that user's HOME.
|
|
75
|
+
--allow-root (sudo only) override default refuse-on-root
|
|
70
76
|
|
|
71
77
|
Global options:
|
|
72
78
|
--no-restart With `config set`: edit .env but skip the restart
|
|
@@ -107,12 +113,77 @@ while [[ $# -gt 0 ]]; do
|
|
|
107
113
|
--no-start) NO_START=1; shift ;;
|
|
108
114
|
--no-restart) NO_RESTART=1; shift ;;
|
|
109
115
|
--yes|-y) ASSUME_YES=1; shift ;;
|
|
116
|
+
--as-user) AS_USER="$2"; shift 2 ;;
|
|
117
|
+
--allow-root) ALLOW_ROOT=1; shift ;;
|
|
110
118
|
-h|--help) usage; exit 0 ;;
|
|
111
119
|
--*) die "Unknown option: $1 (try --help)" ;;
|
|
112
120
|
*) MODE_ARGS+=("$1"); shift ;;
|
|
113
121
|
esac
|
|
114
122
|
done
|
|
115
123
|
|
|
124
|
+
# ─── Root guard: refuse install as root by default ──────────────────────────
|
|
125
|
+
# Running install as root puts data under /root/.local/share/ework-aio, bakes
|
|
126
|
+
# root-only paths into systemd units, and looks for opencode in root's PATH
|
|
127
|
+
# (usually missing). The right answer is almost always: don't use sudo.
|
|
128
|
+
# --as-user re-execs the script as the named user after enabling linger.
|
|
129
|
+
# --allow-root is an explicit acknowledgement that you've set up root's
|
|
130
|
+
# environment (opencode installed, npm prefix configured, etc.).
|
|
131
|
+
if [[ "$MODE" == "install" && "${EUID:-$(id -u)}" == "0" ]]; then
|
|
132
|
+
if [[ -n "$AS_USER" ]]; then
|
|
133
|
+
AS_USER_HOME="$(getent passwd "$AS_USER" 2>/dev/null | cut -d: -f6 || true)"
|
|
134
|
+
AS_USER_UID="$(getent passwd "$AS_USER" 2>/dev/null | cut -d: -f3 || true)"
|
|
135
|
+
if [[ -z "$AS_USER_HOME" || -z "$AS_USER_UID" ]]; then
|
|
136
|
+
die "--as-user: user '$AS_USER' not found in passwd database"
|
|
137
|
+
fi
|
|
138
|
+
if [[ "$AS_USER_UID" == "0" ]]; then
|
|
139
|
+
die "--as-user: target user is root — just use --allow-root instead"
|
|
140
|
+
fi
|
|
141
|
+
log "Enable linger for '$AS_USER' so --user services survive logout..."
|
|
142
|
+
loginctl enable-linger "$AS_USER" \
|
|
143
|
+
|| die "Failed to enable linger for '$AS_USER'. Try: sudo loginctl enable-linger $AS_USER"
|
|
144
|
+
ok "Linger enabled for '$AS_USER'"
|
|
145
|
+
log "Re-execing as '$AS_USER' (HOME=$AS_USER_HOME)..."
|
|
146
|
+
# Strip --as-user <name> from argv, preserve everything else.
|
|
147
|
+
new_args=()
|
|
148
|
+
skip=0
|
|
149
|
+
for a in "$@"; do
|
|
150
|
+
if [[ "$skip" == "1" ]]; then skip=0; continue; fi
|
|
151
|
+
if [[ "$a" == "--as-user" ]]; then skip=1; continue; fi
|
|
152
|
+
new_args+=("$a")
|
|
153
|
+
done
|
|
154
|
+
# Resolve our own path (can't rely on $0 after sudo changes PATH).
|
|
155
|
+
SELF="$(command -v ework-aio 2>/dev/null || true)"
|
|
156
|
+
[[ -n "$SELF" ]] || SELF="${BASH_SOURCE[0]:-$0}"
|
|
157
|
+
exec sudo -u "$AS_USER" --login -- "$SELF" "${new_args[@]}"
|
|
158
|
+
fi
|
|
159
|
+
if [[ "$ALLOW_ROOT" != "1" ]]; then
|
|
160
|
+
cat >&2 <<EOF
|
|
161
|
+
${c_red}ework-aio install refuses to run as root by default.${c_reset}
|
|
162
|
+
|
|
163
|
+
Why this matters:
|
|
164
|
+
- Data goes under /root/.local/share/ework-aio (unreadable by other users)
|
|
165
|
+
- opencode is searched in root's PATH (usually not installed there)
|
|
166
|
+
- npm packages install to system-wide prefix owned by root
|
|
167
|
+
- systemd units bake root-only paths that other users can't run
|
|
168
|
+
|
|
169
|
+
${c_bold}Option A (recommended):${c_reset} run as a regular user.
|
|
170
|
+
npm config set prefix '~/.local' # one-time, makes -g user-writable
|
|
171
|
+
npm install -g ework-aio # no sudo needed
|
|
172
|
+
ework-aio install # uses --user systemd scope
|
|
173
|
+
|
|
174
|
+
${c_bold}Option B:${c_reset} install with sudo but target a regular user.
|
|
175
|
+
sudo ework-aio install --as-user $(logname 2>/dev/null || echo '<your-user>')
|
|
176
|
+
# All data + opencode + npm resolved under that user's HOME.
|
|
177
|
+
# systemd --user scope (linger auto-enabled for the target user).
|
|
178
|
+
|
|
179
|
+
${c_bold}Option C:${c_reset} really install as root (you've set up root's env).
|
|
180
|
+
sudo ework-aio install --allow-root
|
|
181
|
+
EOF
|
|
182
|
+
exit 1
|
|
183
|
+
fi
|
|
184
|
+
warn "Running install as root with --allow-root — data will live under /root."
|
|
185
|
+
fi
|
|
186
|
+
|
|
116
187
|
# Resolve scope: default by uid
|
|
117
188
|
if [[ "$SCOPENAME" == "--user" && "${EUID:-$(id -u)}" == "0" ]]; then
|
|
118
189
|
SCOPENAME="--system"
|
|
@@ -376,19 +447,25 @@ EOF
|
|
|
376
447
|
fi
|
|
377
448
|
}
|
|
378
449
|
|
|
379
|
-
# ctl wraps `systemctl $SCOPENAME` with
|
|
450
|
+
# ctl wraps `systemctl $SCOPENAME` with three hardenings over the bare command:
|
|
380
451
|
# 1. If output contains "Unit ... not found", retry once after daemon-reload
|
|
381
452
|
# — fresh user sessions (no linger, post-ssh-reconnect) often have a stale
|
|
382
453
|
# unit cache and this is the standard fix.
|
|
383
|
-
# 2. If output mentions bus connection failure, print an
|
|
384
|
-
#
|
|
385
|
-
# bus"
|
|
454
|
+
# 2. If output mentions any D-Bus / user-bus connection failure, print an
|
|
455
|
+
# actionable hint. The user-bus daemon emits several variants across
|
|
456
|
+
# hosts and bash versions ("Failed to connect to bus", "No medium found",
|
|
457
|
+
# "Failed to get D-Bus connection: Operation not permitted",
|
|
458
|
+
# "Call to org.freedesktop.DBus ... failed"); we match the common stem
|
|
459
|
+
# "bus" / "D-Bus" so a new variant can't slip past.
|
|
460
|
+
# 3. ALWAYS return systemctl's real exit code. Previously the trailing
|
|
461
|
+
# `printf` masked the failure (returning 0) when no pattern matched,
|
|
462
|
+
# which made every caller's `|| fallback` silently not fire.
|
|
386
463
|
ctl() {
|
|
387
464
|
local out rc
|
|
388
465
|
out="$(systemctl "$SCOPENAME" "$@" 2>&1)"
|
|
389
466
|
rc=$?
|
|
390
467
|
if [[ $rc -ne 0 ]]; then
|
|
391
|
-
if [[ "$out" == *
|
|
468
|
+
if [[ "$out" == *([Bb]us|D-Bus|No medium found)* ]]; then
|
|
392
469
|
cat >&2 <<EOF
|
|
393
470
|
${c_red}systemctl $SCOPENAME failed to reach the user bus.${c_reset}
|
|
394
471
|
$out
|
|
@@ -414,6 +491,7 @@ EOF
|
|
|
414
491
|
fi
|
|
415
492
|
fi
|
|
416
493
|
printf '%s\n' "$out"
|
|
494
|
+
return "$rc"
|
|
417
495
|
}
|
|
418
496
|
|
|
419
497
|
# ─── Config mode: read/change runtime .env keys ─────────────────────────────
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ework-aio",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.14",
|
|
4
4
|
"description": "All-in-one installer for ework (issue tracker) + ework-daemon (AI bridge) + opencode-ework (plugin). One command: npm i -g ework-aio && ework-aio install.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|