mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-05-18 04:41:56 +00:00
fix(install): support non-sudo service-user installs on apt distros (#25814)
The Debian/Ubuntu branch of install_node_deps() ran 'npx playwright install --with-deps chromium' unconditionally. Playwright invokes sudo interactively to apt-install Chromium's system libraries, which blocks the installer for non-sudo users (systemd service accounts, unprivileged operator users) on an unsatisfiable password prompt. Changes: - install.sh: gate --with-deps behind a sudo capability check on the apt branch (matches the existing Arch/pacman branch pattern). Non-sudo users fall back to 'npx playwright install chromium' alone and the installer prints the exact 'sudo npx playwright install-deps chromium' command an administrator can run separately. - install.sh: add --skip-browser (alias --no-playwright) to skip the Playwright step entirely for headless installs that don't need browser automation. Mirrors the existing --no-venv / --skip-setup shape. - installation.md: add a 'Non-Sudo / System Service User Installs' section covering the admin/service-user split, the --skip-browser flag, and the ~/.local/bin PATH gotcha (the root cause of the 'No module named dotenv' error users hit when running the repo source 'hermes' script with system Python instead of the venv launcher). - test_install_sh_browser_install.py: regression coverage for the --skip-browser flag and the sudo-gate on the apt branch. Reported by @ssilver in Discord.
This commit is contained in:
parent
26933c2f59
commit
78b842c995
3 changed files with 100 additions and 6 deletions
|
|
@ -69,6 +69,7 @@ DETECTED_BROWSER_EXECUTABLE=""
|
||||||
# Options
|
# Options
|
||||||
USE_VENV=true
|
USE_VENV=true
|
||||||
RUN_SETUP=true
|
RUN_SETUP=true
|
||||||
|
SKIP_BROWSER=false
|
||||||
BRANCH="main"
|
BRANCH="main"
|
||||||
|
|
||||||
# Detect non-interactive mode (e.g. curl | bash)
|
# Detect non-interactive mode (e.g. curl | bash)
|
||||||
|
|
@ -91,6 +92,10 @@ while [[ $# -gt 0 ]]; do
|
||||||
RUN_SETUP=false
|
RUN_SETUP=false
|
||||||
shift
|
shift
|
||||||
;;
|
;;
|
||||||
|
--skip-browser|--no-playwright)
|
||||||
|
SKIP_BROWSER=true
|
||||||
|
shift
|
||||||
|
;;
|
||||||
--branch)
|
--branch)
|
||||||
BRANCH="$2"
|
BRANCH="$2"
|
||||||
shift 2
|
shift 2
|
||||||
|
|
@ -112,6 +117,7 @@ while [[ $# -gt 0 ]]; do
|
||||||
echo "Options:"
|
echo "Options:"
|
||||||
echo " --no-venv Don't create virtual environment"
|
echo " --no-venv Don't create virtual environment"
|
||||||
echo " --skip-setup Skip interactive setup wizard"
|
echo " --skip-setup Skip interactive setup wizard"
|
||||||
|
echo " --skip-browser Skip Playwright/Chromium install (browser tools won't work)"
|
||||||
echo " --branch NAME Git branch to install (default: main)"
|
echo " --branch NAME Git branch to install (default: main)"
|
||||||
echo " --dir PATH Installation directory"
|
echo " --dir PATH Installation directory"
|
||||||
echo " default (non-root): ~/.hermes/hermes-agent"
|
echo " default (non-root): ~/.hermes/hermes-agent"
|
||||||
|
|
@ -1566,6 +1572,13 @@ install_node_deps() {
|
||||||
# Playwright's --with-deps only supports apt-based systems natively.
|
# Playwright's --with-deps only supports apt-based systems natively.
|
||||||
# For Arch/Manjaro we install the system libs via pacman first.
|
# For Arch/Manjaro we install the system libs via pacman first.
|
||||||
# Other systems must install Chromium dependencies manually.
|
# Other systems must install Chromium dependencies manually.
|
||||||
|
if [ "$SKIP_BROWSER" = true ]; then
|
||||||
|
log_info "Skipping Playwright/Chromium install (--skip-browser)"
|
||||||
|
log_info "Browser tools will be unavailable until you run manually:"
|
||||||
|
log_info " cd $INSTALL_DIR && npx playwright install chromium"
|
||||||
|
log_info "On apt-based systems, an admin also needs to run:"
|
||||||
|
log_info " sudo npx playwright install-deps chromium"
|
||||||
|
else
|
||||||
log_info "Installing browser engine (Playwright Chromium)..."
|
log_info "Installing browser engine (Playwright Chromium)..."
|
||||||
DETECTED_BROWSER_EXECUTABLE="$(find_system_browser 2>/dev/null || true)"
|
DETECTED_BROWSER_EXECUTABLE="$(find_system_browser 2>/dev/null || true)"
|
||||||
if [ -n "$DETECTED_BROWSER_EXECUTABLE" ]; then
|
if [ -n "$DETECTED_BROWSER_EXECUTABLE" ]; then
|
||||||
|
|
@ -1574,12 +1587,30 @@ install_node_deps() {
|
||||||
else
|
else
|
||||||
case "$DISTRO" in
|
case "$DISTRO" in
|
||||||
ubuntu|debian|raspbian|pop|linuxmint|elementary|zorin|kali|parrot)
|
ubuntu|debian|raspbian|pop|linuxmint|elementary|zorin|kali|parrot)
|
||||||
log_info "Playwright may request sudo to install browser system dependencies (shared libraries)."
|
# Use --with-deps only when sudo is available non-interactively
|
||||||
log_info "This is standard Playwright setup — Hermes itself does not require root access."
|
# (root, or a user with passwordless sudo). Non-sudo users
|
||||||
cd "$INSTALL_DIR" && run_browser_install_with_timeout 600 npx playwright install --with-deps chromium 2>/dev/null || {
|
# — typical for systemd service accounts and unprivileged
|
||||||
log_warn "Playwright browser installation failed — browser tools will not work."
|
# operator users — would otherwise get blocked on an
|
||||||
log_warn "Try running manually: cd $INSTALL_DIR && npx playwright install --with-deps chromium"
|
# interactive sudo prompt that they can't satisfy. Fall back
|
||||||
}
|
# to the browser-only install in that case, and print the
|
||||||
|
# exact command the admin needs to run separately.
|
||||||
|
if [ "$(id -u)" -eq 0 ] || (command -v sudo >/dev/null 2>&1 && sudo -n true 2>/dev/null); then
|
||||||
|
log_info "Installing Playwright Chromium with system dependencies..."
|
||||||
|
cd "$INSTALL_DIR" && run_browser_install_with_timeout 600 npx playwright install --with-deps chromium 2>/dev/null || {
|
||||||
|
log_warn "Playwright browser installation failed — browser tools will not work."
|
||||||
|
log_warn "Try running manually: cd $INSTALL_DIR && npx playwright install --with-deps chromium"
|
||||||
|
}
|
||||||
|
else
|
||||||
|
log_warn "No sudo available — skipping system-library install (--with-deps)."
|
||||||
|
log_info "Ask an administrator to run, one time, as root:"
|
||||||
|
log_info " sudo npx playwright install-deps chromium"
|
||||||
|
log_info " (from $INSTALL_DIR, after Node.js deps are installed)"
|
||||||
|
log_info "Installing Chromium binary into this user's Playwright cache..."
|
||||||
|
cd "$INSTALL_DIR" && run_browser_install_with_timeout 600 npx playwright install chromium 2>/dev/null || {
|
||||||
|
log_warn "Playwright browser installation failed — browser tools will not work."
|
||||||
|
log_warn "Try running manually: cd $INSTALL_DIR && npx playwright install chromium"
|
||||||
|
}
|
||||||
|
fi
|
||||||
;;
|
;;
|
||||||
arch|manjaro|cachyos|endeavouros|garuda)
|
arch|manjaro|cachyos|endeavouros|garuda)
|
||||||
if command -v pacman &> /dev/null; then
|
if command -v pacman &> /dev/null; then
|
||||||
|
|
@ -1624,6 +1655,7 @@ install_node_deps() {
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
fi
|
fi
|
||||||
|
fi
|
||||||
log_success "Browser engine setup complete"
|
log_success "Browser engine setup complete"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -32,4 +32,29 @@ def test_playwright_installs_are_timeout_guarded() -> None:
|
||||||
|
|
||||||
assert "run_browser_install_with_timeout()" in text
|
assert "run_browser_install_with_timeout()" in text
|
||||||
assert "run_browser_install_with_timeout 600 npx playwright install chromium" in text
|
assert "run_browser_install_with_timeout 600 npx playwright install chromium" in text
|
||||||
|
# --with-deps is still invoked on apt-based systems, but only when sudo
|
||||||
|
# is available non-interactively (root or passwordless sudo). Non-sudo
|
||||||
|
# service users fall back to the browser-only install — see
|
||||||
|
# install_node_deps() in install.sh.
|
||||||
assert "run_browser_install_with_timeout 600 npx playwright install --with-deps chromium" in text
|
assert "run_browser_install_with_timeout 600 npx playwright install --with-deps chromium" in text
|
||||||
|
|
||||||
|
|
||||||
|
def test_install_script_supports_skip_browser_flag() -> None:
|
||||||
|
"""--skip-browser (and --no-playwright alias) skips the Playwright install."""
|
||||||
|
text = INSTALL_SH.read_text()
|
||||||
|
|
||||||
|
assert "--skip-browser|--no-playwright)" in text
|
||||||
|
assert "SKIP_BROWSER=true" in text
|
||||||
|
assert 'if [ "$SKIP_BROWSER" = true ]; then' in text
|
||||||
|
assert "--skip-browser Skip Playwright/Chromium install" in text
|
||||||
|
|
||||||
|
|
||||||
|
def test_install_script_skips_with_deps_when_no_sudo() -> None:
|
||||||
|
"""Non-sudo users on apt distros must not block on an interactive sudo prompt."""
|
||||||
|
text = INSTALL_SH.read_text()
|
||||||
|
|
||||||
|
# The apt branch must gate --with-deps behind a sudo capability check
|
||||||
|
# (root or non-interactive sudo), otherwise the installer hangs for
|
||||||
|
# service-user installs (systemd accounts, operator users, etc.).
|
||||||
|
assert 'if [ "$(id -u)" -eq 0 ] || (command -v sudo >/dev/null 2>&1 && sudo -n true 2>/dev/null); then' in text
|
||||||
|
assert "sudo npx playwright install-deps chromium" in text
|
||||||
|
|
|
||||||
|
|
@ -132,6 +132,43 @@ If you want to clone the repo and install from source — for contributing, runn
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## Non-Sudo / System Service User Installs
|
||||||
|
|
||||||
|
Running Hermes as a dedicated unprivileged user (e.g. a `hermes` systemd service account, or any user without `sudo` access) is supported. The only thing on the install path that genuinely needs root is Playwright's `--with-deps` step, which `apt`-installs shared libraries (`libnss3`, `libxkbcommon`, etc.) used by Chromium. The installer detects whether sudo is available and gracefully degrades when it isn't — it will install the Chromium binary into the service user's own Playwright cache and print the exact command an administrator needs to run separately.
|
||||||
|
|
||||||
|
**Recommended split (Debian/Ubuntu):**
|
||||||
|
|
||||||
|
1. **One time, as an admin user with sudo**, install the system libraries Chromium needs:
|
||||||
|
```bash
|
||||||
|
sudo npx playwright install-deps chromium
|
||||||
|
```
|
||||||
|
(You can run this from anywhere — `npx` will fetch Playwright on the fly.)
|
||||||
|
|
||||||
|
2. **As the unprivileged service user**, run the regular installer. It will detect the missing sudo, skip `--with-deps`, and install Chromium into the user's local Playwright cache:
|
||||||
|
```bash
|
||||||
|
curl -fsSL https://raw.githubusercontent.com/NousResearch/hermes-agent/main/scripts/install.sh | bash
|
||||||
|
```
|
||||||
|
|
||||||
|
If you want to skip the Playwright step entirely — for example because you're running headless and don't need browser automation — pass `--skip-browser`:
|
||||||
|
```bash
|
||||||
|
curl -fsSL https://raw.githubusercontent.com/NousResearch/hermes-agent/main/scripts/install.sh | bash -s -- --skip-browser
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **Make `hermes` available to the service user's shells.** The installer writes the launcher to `~/.local/bin/hermes`. System service accounts often have a minimal PATH that doesn't include `~/.local/bin`. Either add it to the user's environment, or symlink the launcher into a system location:
|
||||||
|
```bash
|
||||||
|
# Option A — add to the service user's profile
|
||||||
|
echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.bashrc
|
||||||
|
|
||||||
|
# Option B — symlink system-wide (run as an admin)
|
||||||
|
sudo ln -s /home/hermes/.hermes/hermes-agent/venv/bin/hermes /usr/local/bin/hermes
|
||||||
|
```
|
||||||
|
|
||||||
|
4. **Verify:** `hermes doctor` should now run cleanly. If you get `ModuleNotFoundError: No module named 'dotenv'`, you're invoking the repo source `hermes` file (`~/.hermes/hermes-agent/hermes`) with system Python instead of the venv launcher (`~/.hermes/hermes-agent/venv/bin/hermes`) — fix step 3.
|
||||||
|
|
||||||
|
The same pattern works on Arch (the installer uses pacman with the same sudo-detection logic), Fedora/RHEL, and openSUSE — those distros don't support `--with-deps` at all, so an administrator always installs the system libraries separately. The relevant `dnf`/`zypper` commands are printed by the installer.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Troubleshooting
|
## Troubleshooting
|
||||||
|
|
||||||
| Problem | Solution |
|
| Problem | Solution |
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue