{"record":{"id":"a917e897b1dd6609","repo":"NousResearch/hermes-agent","slug":"openssl-not-found-on-path-install-openssl-apt","errorCode":null,"errorMessage":"openssl not found on PATH. Install OpenSSL (apt: `openssl`, brew: `openssl`) to generate the iron-proxy CA cert.","messagePattern":"openssl not found on PATH\\. Install OpenSSL \\(apt: `openssl`, brew: `openssl`\\) to generate the iron-proxy CA cert\\.","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"agent/proxy_sources/iron_proxy.py","lineNumber":747,"sourceCode":"\ndef ensure_ca_cert(*, force: bool = False) -> Tuple[Path, Path]:\n    \"\"\"Generate (or return existing) iron-proxy CA cert + key.\n\n    Uses the host's ``openssl`` binary.  We don't try to bind to a Python\n    crypto library — openssl is universally available on the platforms we\n    support, and it sidesteps cryptography-package licensing/distribution\n    surface.\n    \"\"\"\n\n    state = _proxy_state_dir()\n    ca_crt = state / \"ca.crt\"\n    ca_key = state / \"ca.key\"\n\n    if ca_crt.exists() and ca_key.exists() and not force:\n        return ca_crt, ca_key\n\n    if shutil.which(\"openssl\") is None:\n        raise RuntimeError(\n            \"openssl not found on PATH. Install OpenSSL (apt: `openssl`, \"\n            \"brew: `openssl`) to generate the iron-proxy CA cert.\"\n        )\n\n    # 10-year cert.  iron-proxy mints short-lived leaf certs from this CA,\n    # so the CA itself only rotates when the user explicitly forces it.\n    with tempfile.TemporaryDirectory(prefix=\"hermes-proxy-ca-\") as tmpdir:\n        tmp = Path(tmpdir)\n        tmp_key = tmp / \"ca.key\"\n        tmp_crt = tmp / \"ca.crt\"\n\n        subprocess.run(  # noqa: S603 — openssl path is trusted PATH lookup\n            [\"openssl\", \"genrsa\", \"-out\", str(tmp_key), \"4096\"],\n            check=True,\n            capture_output=True,\n            timeout=60,\n        )\n        subprocess.run(  # noqa: S603","sourceCodeStart":729,"sourceCodeEnd":765,"githubUrl":"https://github.com/NousResearch/hermes-agent/blob/c896c09c42910c584c4c7d2325b58c14713ea42c/agent/proxy_sources/iron_proxy.py#L729-L765","documentation":"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.","triggerScenarios":"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.","commonSituations":"python:*-slim Docker images and distroless-adjacent containers; macOS after removing/renaming Homebrew openssl; first-ever `hermes egress setup` on a stripped-down server.","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."],"exampleFix":"// before\nensure_ca_cert(force=True)  # RuntimeError: openssl not found on PATH\n\n// after\nimport shutil\nif shutil.which(\"openssl\") is None:\n    raise SystemExit(\"install openssl first: apt-get install -y openssl\")\nensure_ca_cert(force=True)","handlingStrategy":"validation","validationCode":"import shutil\n\ndef can_generate_ca() -> bool:\n    return shutil.which(\"openssl\") is not None","typeGuard":null,"tryCatchPattern":"try:\n    ensure_ca_cert()\nexcept RuntimeError as e:\n    if \"openssl not found\" in str(e):\n        raise SystemExit(\"Install openssl (apt: openssl, brew: openssl) before egress setup\")","preventionTips":["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."],"tags":["dependencies","certificates","openssl","iron-proxy"],"backgroundTag":null,"analyzedSha":"c896c09c42910c584c4c7d2325b58c14713ea42c","analyzedAt":"2026-08-14T17:18:01.089Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}