feat: add Hermes Agent LXC#1777
Open
steveonjava wants to merge 28 commits into
Open
Conversation
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.
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.
19b5949 to
06d9c62
Compare
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.
CrazyWolf13
requested changes
May 5, 2026
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.
Contributor
Author
|
Thanks for the feedback, @CrazyWolf13. I addressed all of it and retested to make sure the installer works end-to-end. |
CrazyWolf13
requested changes
May 10, 2026
6c4eca4 to
43cc3c8
Compare
…DE_OPTIONS from setup_nodejs
…dundant EnvironmentFile for .env
…env vars and HERMES_HOME
…m installer includes web,pty extras in .[all]
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. |
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
CrazyWolf13
reviewed
May 11, 2026
CrazyWolf13
requested changes
May 11, 2026
19 tasks
…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.
Contributor
Author
|
@CrazyWolf13 I responded and made the fixes you highlighted. Let me know if you want any other changes. |
CrazyWolf13
requested changes
May 12, 2026
Removed an unnecessary space. Co-authored-by: Tobias <96661824+CrazyWolf13@users.noreply.github.com>
CrazyWolf13
approved these changes
May 15, 2026
michelroegl-brunner
approved these changes
May 16, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
✍️ 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.shinstall/hermes-agent-install.shjson/hermes-agent.jsonct/headers/hermes-agentDeviations from standard patterns (justified):
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.Dedicated
hermesservice 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.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.
/usr/bin/hermesshim script: The hermes CLI validates cwd permissions; runninghermesas root from/rootfails. The shimcds to/home/hermesandexecs as the hermes user viarunuser. This gives the expected user experience when you login as root and want to run hermes setup or other commands.setsid --waitwrapping of upstream installer: The upstream installer probes/dev/ttyfor interactive prompts even with--skip-setup;setsiddetaches the controlling terminal. This ensures the installer has no unwanted output.🔗 Related PR / Issue
Link: #
✅ Prerequisites (X in brackets)
🛠️ Type of Change (X in brackets)
README,AppName.md,CONTRIBUTING.md, or other docs.🔍 Code & Security Review (X in brackets)
Code_Audit.md&CONTRIBUTING.mdguidelinesAppName.sh,AppName-install.sh,AppName.json)📋 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)
🌐 Source