Skip to content

feat: add Hermes Agent LXC#1777

Open
steveonjava wants to merge 28 commits into
community-scripts:mainfrom
steveonjava:feat/hermes-agent
Open

feat: add Hermes Agent LXC#1777
steveonjava wants to merge 28 commits into
community-scripts:mainfrom
steveonjava:feat/hermes-agent

Conversation

@steveonjava
Copy link
Copy Markdown
Contributor

✍️ Description

Adds container scripts for Hermes Agent (Nous Research), a self-improving AI agent with LLM provider integration, terminal execution, web browsing, and multi-platform messaging support. This LXC installs hermes and configures the API gateway and dashboard. The user needs to complete guided setup and connect it to a model and optionally gateways in order for it to be fully functional.

Files:

  • ct/hermes-agent.sh
  • install/hermes-agent-install.sh
  • json/hermes-agent.json
  • ct/headers/hermes-agent

Deviations from standard patterns (justified):

  1. Uses upstream installer (curl-pipe) instead of fetch_and_deploy_gh_release: Hermes is a uv-managed Python application with complex dependency resolution, virtualenv management, and binary placement—not a single binary or tarball from GitHub Releases.

  2. Dedicated hermes service user (not running as root): The agent executes arbitrary terminal commands on behalf of the user. Running as root would give the AI unrestricted system access. This follows the protonmail-bridge service-user pattern for isolation. The hermes installer and update tasks are run as root to install required dependencies unattended.

  3. Dashboard (port 9119) bound to localhost only, requiring SSH tunnel: The web UI provides admin access to an AI that can execute commands. SSH tunnel provides an authentication/authorization boundary. If hermes provides a secure/authenticated dashboard in the future this should be revisited.

  4. /usr/bin/hermes shim script: The hermes CLI validates cwd permissions; running hermes as root from /root fails. The shim cds to /home/hermes and execs as the hermes user via runuser. This gives the expected user experience when you login as root and want to run hermes setup or other commands.

  5. setsid --wait wrapping of upstream installer: The upstream installer probes /dev/tty for interactive prompts even with --skip-setup; setsid detaches the controlling terminal. This ensures the installer has no unwanted output.

🔗 Related PR / Issue

Link: #

✅ Prerequisites (X in brackets)

  • Self-review completed – Code follows project standards.
  • Tested thoroughly – Changes work as expected.
  • No breaking changes – Existing functionality remains intact.
  • No security risks – No hardcoded secrets, unnecessary privilege escalations, or permission issues.

🛠️ Type of Change (X in brackets)

  • 🐞 Bug fix – Resolves an issue without breaking functionality.
  • New feature – Adds new, non-breaking functionality.
  • 💥 Breaking change – Alters existing functionality in a way that may require updates.
  • 🆕 New script – A fully functional and tested script or script set.
  • 🌍 Website update – Changes to website-related JSON files or metadata.
  • 🔧 Refactoring / Code Cleanup – Improves readability or maintainability without changing functionality.
  • 📝 Documentation update – Changes to README, AppName.md, CONTRIBUTING.md, or other docs.

🔍 Code & Security Review (X in brackets)

  • Follows Code_Audit.md & CONTRIBUTING.md guidelines
  • Uses correct script structure (AppName.sh, AppName-install.sh, AppName.json)
  • No hardcoded credentials

📋 Additional Information (optional)

Initial script structure was AI-assisted, then iteratively revised by the author across ~60 commits to pass linting, resolve install failures in a live Proxmox environment, align with repo conventions, and address security concerns (service user isolation, sudoers scope hardening, localhost-only dashboard binding).


📦 Application Requirements (for new scripts)

Required for 🆕 New script submissions.
Pull requests that do not meet these requirements may be closed without review.

  • The application is at least 6 months old (repo renamed from OpenClaw to hermes-agent in late 2025; the project and its community predate the rename)
  • The application is actively maintained
  • The application has 600+ GitHub stars (129k stars)
  • Official release tarballs are published
  • I understand that not all scripts will be accepted due to various reasons and criteria by the community-scripts ORG

🌐 Source

Adds container scripts for Hermes Agent (Nous Research), a self-improving
AI agent with LLM provider integration, terminal execution, web browsing,
and multi-platform messaging support.

Files:
- ct/hermes-agent.sh
- install/hermes-agent-install.sh
- json/hermes-agent.json
- ct/headers/hermes-agent

Deviations from standard patterns (justified):

1. Uses upstream installer (curl-pipe) instead of fetch_and_deploy_gh_release:
   Hermes is a uv-managed Python application with complex dependency
   resolution, virtualenv management, and binary placement—not a single
   binary or tarball from GitHub Releases.

2. Dedicated 'hermes' service user (not running as root):
   The agent executes arbitrary terminal commands on behalf of the user.
   Running as root would give the AI unrestricted system access. This
   follows the protonmail-bridge service-user pattern for isolation.

3. Dashboard (port 9119) bound to localhost only, requiring SSH tunnel:
   The web UI provides admin access to an AI that can execute commands.
   SSH tunnel provides an authentication/authorization boundary.

4. /usr/bin/hermes shim script:
   The hermes CLI validates cwd permissions; running 'hermes' as root
   from /root fails. The shim cd's to /home/hermes and exec's as the
   hermes user via runuser.

5. setsid --wait wrapping of upstream installer:
   The upstream installer probes /dev/tty for interactive prompts even
   with --skip-setup; setsid detaches the controlling terminal.
@steveonjava steveonjava requested a review from a team as a code owner May 2, 2026 13:45
HERMES_REDACT_SECRETS is off by default, exposing API keys in chat output
and session JSON files. Add HERMES_REDACT_SECRETS=true to the .env file
created by the installer.

Ref: NousResearch/hermes-agent#17691
The Anthropic OAuth helper writes credential files with the process
default umask, resulting in 0644 permissions on sensitive files. Set
UMask=0077 on both hermes-gateway and hermes-dashboard services so all
files created at runtime are owner-only (0600/0700).

Ref: NousResearch/hermes-agent#11003
Hermes strips sensitive env vars from tool subprocesses, but child
processes can recover them by reading /proc/<parent_pid>/environ. Add
ProtectProc=invisible and ProcSubset=pid to both systemd services to
hide other processes' /proc entries and limit /proc to the service's
own PID namespace.

Ref: NousResearch/hermes-agent#4427
The response_store.db and session JSON files under ~/.hermes/ are stored
in plaintext and readable by any process with filesystem access. Set
~/.hermes to 0700 (owner-only) and ~/home/hermes to 0750 to restrict
access to conversation history, credentials, and session data.

Ref: NousResearch/hermes-agent#7486
APP='Hermes Agent' produces NSAPP='hermesagent' via build.func's
lowercase+strip-spaces logic. Rename ct/, install/, json/, and
header files to match.
@steveonjava steveonjava force-pushed the feat/hermes-agent branch from 19b5949 to 06d9c62 Compare May 2, 2026 16:46
The hermes service account has no password or SSH keys and cannot
be used to log in. Access is via root (standard PVE Helper Scripts
pattern). Also add -fN flags to the dashboard tunnel command so it
runs in the background without opening a shell session.
- default_credentials: username null/null (no SSH login for hermes
  service account; access is via root like all PVE Helper Scripts)
- Update setup note to reference root instead of hermes user
- Update dashboard tunnel note to use root and -fNL flags
…ompt

hermes update prompts "Restore local changes now? [Y/n]" when run
in a TTY context. --yes skips all interactive prompts.
runuser requires root. When the hermes user calls the shim directly
(e.g. via su - hermes), exec the binary directly instead.
…e user services

The previous approach used a /usr/bin/hermes shim to proxy commands from root
to the hermes user, and a hand-crafted system-level systemd unit for the
gateway. This worked for the default profile but broke down for named profiles:

- hermes profile create <name> generates an alias script in
  ~/.local/bin/<name> that calls hermes with -p <name>. These aliases live
  in the hermes user's PATH, not root's, so root could not invoke them.
- Maintaining parity would require per-profile shims, a watcher daemon to
  create/remove them, and system-unit mirrors for each profile gateway — all
  of which would need to stay in sync with hermes internals across updates.

New approach — work with hermes, not around it:

- loginctl enable-linger hermes: ensures the hermes user's systemd session
  starts at boot and persists without login. All user-unit gateways (default
  and per-profile) now survive reboots automatically.
- Gateway service management delegated entirely to hermes: 'hermes gateway
  install' / 'hermes setup' create and enable the user unit natively.
  The install script no longer pre-installs the gateway; hermes prompts the
  user to do so at the end of 'hermes setup'.
- hermes-dashboard.service remains a system unit (no native install command
  exists for it). Its After= no longer references hermes-gateway.service
  since there is no system-unit gateway to depend on.
- /usr/bin/hermes shim removed. Root is guided to 'su - hermes' via a two-
  line /etc/profile.d/hermes-hint.sh message on login, with a one-liner to
  make the switch automatic. Once logged in as hermes, all hermes commands,
  profile aliases, and gateway management work natively.
- update_script simplified: only hermes-dashboard (our unit) is stopped and
  restarted. hermes update --yes handles gateway service lifecycle itself.
Comment thread ct/hermesagent.sh Outdated
Comment thread install/hermesagent-install.sh Outdated
Comment thread install/hermesagent-install.sh Outdated
Comment thread install/hermesagent-install.sh Outdated
Trims the verbose 12-line CT footer to the standard pattern plus
essential first-run setup steps. API server, API key, and dashboard
SSH tunnel details are now displayed on every SSH login via
/etc/profile.d/hermes-hint.sh instead.

Addresses PR feedback from CrazyWolf13.
Adds third-party script warning with user confirmation before running
the upstream installer (install) and updater (update), matching the
kasm/pihole pattern. Removes redundant binary existence check per
reviewer feedback. Adds corresponding JSON warning note.
@steveonjava
Copy link
Copy Markdown
Contributor Author

Thanks for the feedback, @CrazyWolf13. I addressed all of it and retested to make sure the installer works end-to-end.

@steveonjava steveonjava requested a review from CrazyWolf13 May 10, 2026 14:38
Comment thread ct/hermesagent.sh Outdated
Comment thread ct/hermesagent.sh Outdated
Comment thread install/hermesagent-install.sh
Comment thread install/hermesagent-install.sh Outdated
Comment thread install/hermesagent-install.sh Outdated
Comment thread install/hermesagent-install.sh
@steveonjava
Copy link
Copy Markdown
Contributor Author

@CrazyWolf13 I made fixes for your above comments and also tried to capture additional changes that were in the spirit of cleaning up the install output, minimizing the motd, and following script defaults. Let me know if you see anything else that can be improved.

@steveonjava steveonjava requested a review from CrazyWolf13 May 11, 2026 00:22
hermes-agent v2026.5.7 (PR #21193, merged 2026-05-07) flipped
HERMES_REDACT_SECRETS and DEFAULT_CONFIG security.redact_secrets to
true by default. The explicit HERMES_REDACT_SECRETS=true in .env and
the config.yaml creation block added in commit 1420682 are now
redundant — Hermes writes the same values itself on a fresh install.

Verified on CT 900 (v2026.5.7): _REDACT_ENABLED=True with no env
override; Hermes self-writes redact_secrets: true to config.yaml.

Ref: NousResearch/hermes-agent#17691
Comment thread install/hermesagent-install.sh
Comment thread install/hermesagent-install.sh
Comment thread json/hermesagent.json Outdated
…o .env

- Drop 'WARNING: '/'Warning: ' prefixes from note texts — the type:warning
  field already communicates severity (per CrazyWolf13 review feedback)
- Set config_path to /home/hermes/.hermes/.env (was directory path)
Resolve  to 'Hermes Agent' in all msg_info/msg_ok/msg_error
calls per CrazyWolf13 review feedback — improves readability for users
reading install output.
@steveonjava
Copy link
Copy Markdown
Contributor Author

@CrazyWolf13 I responded and made the fixes you highlighted. Let me know if you want any other changes.

@steveonjava steveonjava requested a review from CrazyWolf13 May 12, 2026 00:44
Comment thread ct/hermesagent.sh Outdated
Comment thread install/hermesagent-install.sh
Comment thread install/hermesagent-install.sh
Comment thread install/hermesagent-install.sh
Removed an unnecessary space.

Co-authored-by: Tobias <96661824+CrazyWolf13@users.noreply.github.com>
@steveonjava steveonjava requested a review from CrazyWolf13 May 15, 2026 03:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants