commit b3c59a5d69f69b8a2dc92575e4ca49f71feaff16 Author: Mathieu BOURBON Date: Wed Jun 3 20:56:41 2026 +0200 feat: initial hermes-agent role diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a8b42eb --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +*.retry diff --git a/README.md b/README.md new file mode 100644 index 0000000..71b3f01 --- /dev/null +++ b/README.md @@ -0,0 +1,30 @@ +# ansible-role-hermes + +Install [Hermes Agent](https://github.com/NousResearch/hermes-agent) (NousResearch) as a systemd service on Linux. + +Hermes est installé dans un virtualenv Python isolé depuis le wheel publié sur GitHub Releases. + +## Variables + +| Variable | Défaut | Description | +|---|---|---| +| `hermes_version` | `""` | Version à installer (ex: `0.15.2`). Vide = dernière version. | +| `hermes_user` | `hermes` | Utilisateur système | +| `hermes_group` | `hermes` | Groupe système | +| `hermes_install_dir` | `/opt/hermes` | Répertoire d'installation (venv + binaire) | +| `hermes_data_dir` | `/var/lib/hermes` | Répertoire de données (`HERMES_HOME`) | +| `hermes_service_enabled` | `true` | Activer le service au démarrage | +| `hermes_service_state` | `started` | État du service | +| `hermes_env` | `{}` | Variables d'environnement supplémentaires (clés API, etc.) | + +## Exemple + +```yaml +- hosts: ai_servers + roles: + - role: ansible-role-hermes + vars: + hermes_env: + OPENAI_API_KEY: "sk-..." + ANTHROPIC_API_KEY: "sk-ant-..." +``` diff --git a/defaults/main.yml b/defaults/main.yml new file mode 100644 index 0000000..5e23857 --- /dev/null +++ b/defaults/main.yml @@ -0,0 +1,9 @@ +--- +hermes_version: "" +hermes_user: hermes +hermes_group: hermes +hermes_install_dir: /opt/hermes +hermes_data_dir: /var/lib/hermes +hermes_service_enabled: true +hermes_service_state: started +hermes_env: {} diff --git a/handlers/main.yml b/handlers/main.yml new file mode 100644 index 0000000..ed97d53 --- /dev/null +++ b/handlers/main.yml @@ -0,0 +1 @@ +--- diff --git a/meta/main.yml b/meta/main.yml new file mode 100644 index 0000000..1cdb79f --- /dev/null +++ b/meta/main.yml @@ -0,0 +1,15 @@ +--- +galaxy_info: + author: mathieu + description: Install Hermes Agent (NousResearch) via wheel on Linux + license: MIT + min_ansible_version: "2.14" + platforms: + - name: Debian + versions: [bullseye, bookworm] + - name: Ubuntu + versions: [focal, jammy, noble] + - name: EL + versions: ["8", "9"] + galaxy_tags: [hermes, ai, agent] +dependencies: [] diff --git a/tasks/main.yml b/tasks/main.yml new file mode 100644 index 0000000..a324353 --- /dev/null +++ b/tasks/main.yml @@ -0,0 +1,132 @@ +--- +- name: Install prerequisites + ansible.builtin.package: + name: + - python3 + - python3-pip + - python3-venv + - curl + state: present + become: true + +- name: Create Hermes group + ansible.builtin.group: + name: "{{ hermes_group }}" + system: true + state: present + become: true + +- name: Create Hermes user + ansible.builtin.user: + name: "{{ hermes_user }}" + group: "{{ hermes_group }}" + home: "{{ hermes_data_dir }}" + shell: /usr/sbin/nologin + system: true + create_home: false + state: present + become: true + +- name: Get Hermes release info from GitHub + ansible.builtin.uri: + url: >- + {{ 'https://api.github.com/repos/NousResearch/hermes-agent/releases/latest' + if hermes_version == '' + else 'https://api.github.com/repos/NousResearch/hermes-agent/releases/tags/v' + hermes_version }} + headers: + Accept: "application/vnd.github.v3+json" + return_content: true + register: _hermes_release + +- name: Set version and download URL facts + ansible.builtin.set_fact: + _hermes_version_tag: "{{ _hermes_release.json.tag_name }}" + _hermes_whl_url: >- + {{ _hermes_release.json.assets + | selectattr('name', 'search', '\.whl$') + | map(attribute='browser_download_url') + | first }} + +- name: Read installed version + ansible.builtin.slurp: + src: "{{ hermes_install_dir }}/.version" + register: _hermes_installed_raw + ignore_errors: true + become: true + +- name: Set installed version fact + ansible.builtin.set_fact: + _hermes_installed_version: >- + {{ (_hermes_installed_raw.content | b64decode | trim) + if _hermes_installed_raw is not failed else '' }} + +- name: Install or upgrade Hermes + when: _hermes_installed_version != _hermes_version_tag + block: + - name: Create Hermes installation directory + ansible.builtin.file: + path: "{{ hermes_install_dir }}" + state: directory + owner: "{{ hermes_user }}" + group: "{{ hermes_group }}" + mode: '0755' + become: true + + - name: Create Python virtual environment + ansible.builtin.command: + cmd: python3 -m venv {{ hermes_install_dir }}/venv + creates: "{{ hermes_install_dir }}/venv/bin/python" + become: true + become_user: "{{ hermes_user }}" + + - name: Download Hermes wheel + ansible.builtin.get_url: + url: "{{ _hermes_whl_url }}" + dest: /tmp/hermes.whl + mode: '0644' + + - name: Install Hermes wheel into virtualenv + ansible.builtin.pip: + name: /tmp/hermes.whl + virtualenv: "{{ hermes_install_dir }}/venv" + state: present + become: true + become_user: "{{ hermes_user }}" + + - name: Write installed version file + ansible.builtin.copy: + content: "{{ _hermes_version_tag }}" + dest: "{{ hermes_install_dir }}/.version" + owner: "{{ hermes_user }}" + group: "{{ hermes_group }}" + mode: '0644' + become: true + + - name: Remove downloaded wheel + ansible.builtin.file: + path: /tmp/hermes.whl + state: absent + +- name: Create Hermes data directory + ansible.builtin.file: + path: "{{ hermes_data_dir }}" + state: directory + owner: "{{ hermes_user }}" + group: "{{ hermes_group }}" + mode: '0750' + become: true + +- name: Create Hermes systemd service + ansible.builtin.template: + src: hermes.service.j2 + dest: /etc/systemd/system/hermes.service + mode: '0644' + become: true + +- name: Enable and start Hermes service + ansible.builtin.systemd: + name: hermes + enabled: "{{ hermes_service_enabled }}" + state: "{{ hermes_service_state }}" + daemon_reload: true + become: true diff --git a/templates/hermes.service.j2 b/templates/hermes.service.j2 new file mode 100644 index 0000000..24f420c --- /dev/null +++ b/templates/hermes.service.j2 @@ -0,0 +1,17 @@ +[Unit] +Description=Hermes Agent +After=network.target + +[Service] +User={{ hermes_user }} +Group={{ hermes_group }} +Environment=HERMES_HOME={{ hermes_data_dir }} +{% for key, value in hermes_env.items() %} +Environment={{ key }}={{ value }} +{% endfor %} +ExecStart={{ hermes_install_dir }}/venv/bin/hermes run +Restart=on-failure +RestartSec=5s + +[Install] +WantedBy=multi-user.target