NousResearch/hermes-agent · error · RuntimeError
openssl not found on PATH. Install OpenSSL (apt: `openssl`,
Error message
openssl not found on PATH. Install OpenSSL (apt: `openssl`, brew: `openssl`) to generate the iron-proxy CA cert.
What it means
ensure_ca_cert() generates the local CA (used by iron-proxy to mint short-lived leaf certs for TLS interception) by shelling out to the `openssl` CLI, avoiding a cryptography-package dependency. If shutil.which('openssl') is None it refuses with an actionable install hint. Existing ca.crt/ca.key short-circuit this, so it only fires when the CA must actually be (re)generated.
Source
Thrown at agent/proxy_sources/iron_proxy.py:747
def ensure_ca_cert(*, force: bool = False) -> Tuple[Path, Path]:
"""Generate (or return existing) iron-proxy CA cert + key.
Uses the host's ``openssl`` binary. We don't try to bind to a Python
crypto library — openssl is universally available on the platforms we
support, and it sidesteps cryptography-package licensing/distribution
surface.
"""
state = _proxy_state_dir()
ca_crt = state / "ca.crt"
ca_key = state / "ca.key"
if ca_crt.exists() and ca_key.exists() and not force:
return ca_crt, ca_key
if shutil.which("openssl") is None:
raise RuntimeError(
"openssl not found on PATH. Install OpenSSL (apt: `openssl`, "
"brew: `openssl`) to generate the iron-proxy CA cert."
)
# 10-year cert. iron-proxy mints short-lived leaf certs from this CA,
# so the CA itself only rotates when the user explicitly forces it.
with tempfile.TemporaryDirectory(prefix="hermes-proxy-ca-") as tmpdir:
tmp = Path(tmpdir)
tmp_key = tmp / "ca.key"
tmp_crt = tmp / "ca.crt"
subprocess.run( # noqa: S603 — openssl path is trusted PATH lookup
["openssl", "genrsa", "-out", str(tmp_key), "4096"],
check=True,
capture_output=True,
timeout=60,
)
subprocess.run( # noqa: S603View on GitHub (pinned to c896c09c42)
Solutions
- Install OpenSSL: `apt-get install -y openssl` (Debian/Ubuntu), `apk add openssl` (Alpine), or `brew install openssl` (macOS) and ensure it is on PATH.
- If you already have a CA, place ca.crt and ca.key in the proxy state dir so ensure_ca_cert() reuses them instead of generating.
- For containers, add openssl to the image rather than installing at runtime.
Example fix
// before
ensure_ca_cert(force=True) # RuntimeError: openssl not found on PATH
// after
import shutil
if shutil.which("openssl") is None:
raise SystemExit("install openssl first: apt-get install -y openssl")
ensure_ca_cert(force=True) Defensive patterns
Strategy: validation
Validate before calling
import shutil
def can_generate_ca() -> bool:
return shutil.which("openssl") is not None Try / catch
try:
ensure_ca_cert()
except RuntimeError as e:
if "openssl not found" in str(e):
raise SystemExit("Install openssl (apt: openssl, brew: openssl) before egress setup") Prevention
- Add openssl to base container images used with the egress proxy.
- Reuse an existing CA by placing ca.crt/ca.key in the proxy state dir instead of regenerating.
- Check for openssl during machine provisioning, not at first setup run.
When it happens
Trigger: Calling ensure_ca_cert() or ensure_ca_cert(force=True) (or `hermes egress setup`) on a host without the openssl binary on PATH — minimal containers (slim Docker images), hardened base images, or systems where openssl is installed but not on PATH.
Common situations: python:*-slim Docker images and distroless-adjacent containers; macOS after removing/renaming Homebrew openssl; first-ever `hermes egress setup` on a stripped-down server.
Related errors
- PyYAML is required to write the iron-proxy config but is not
- The 'azure-identity' package is required for Azure AI Foundr
- httpx is required for Entra ID bearer auth on Microsoft Foun
- The 'boto3' package is required for the AWS Bedrock provider
- boto3 {boto3.__version__} does not support converse_stream (
AI-assisted analysis of NousResearch/hermes-agent@c896c09c42 (2026-08-14).
Data as JSON: /api/errors/a917e897b1dd6609.
Report an issue: GitHub.