--- # ============================================================================= # multica_agent_host — defaults # # Everything the role needs is a plain variable. The role never reaches into a # secrets backend itself; see `multica_pat` below. # ============================================================================= # ----------------------------------------------------------------------------- # Service account # ----------------------------------------------------------------------------- # The daemon runs as a dedicated unprivileged user with a real home directory. # It needs a real home (CLI config, agent CLI credentials) and systemd linger, # so this is NOT a `system: true` account. multica_manage_user: true multica_user: multica multica_group: multica multica_user_home: "/home/{{ multica_user }}" multica_user_shell: /bin/bash # Extra groups for the daemon user (e.g. docker). Left empty by default. multica_user_extra_groups: [] # ----------------------------------------------------------------------------- # multica CLI — Ansible owns the version # ----------------------------------------------------------------------------- # Pin it. Re-running the play IS the upgrade path; see multica_disable_auto_update. multica_version: "0.6.5" multica_install_dir: /usr/local/bin multica_release_download_base_url: "https://github.com/multica-ai/multica/releases/download" # Verify the release tarball against the release's own checksums.txt. multica_verify_checksum: true # ----------------------------------------------------------------------------- # Server / workspace # ----------------------------------------------------------------------------- multica_server_url: "" # REQUIRED, e.g. https://multica.wdw-labs.cloud multica_app_url: "" # optional frontend URL multica_workspace_id: "" # optional: pin this profile's default workspace multica_profile: "" # optional: --profile (isolates config + daemon state) # ----------------------------------------------------------------------------- # Daemon configuration (mirrors `multica config set` keys) # ----------------------------------------------------------------------------- # Local disk by default. Repoint this at a mount when one exists, and set # multica_workspaces_root_mount at the same time so the play fails loudly if # the mount is missing rather than silently filling the root filesystem. multica_workspaces_root: "/opt/multica/workspaces" # Optional guard: assert workspaces_root actually sits on this mount point. # e.g. "/mnt/utilidor". Empty disables the check. multica_workspaces_root_mount: "" multica_workspaces_root_mode: "0750" multica_device_name: "{{ inventory_hostname.split('.')[0] }}" multica_runtime_name: "" # "" = leave unset, CLI derives it multica_max_concurrent_tasks: "" # "" = leave unset multica_poll_interval: "" # "" = leave unset multica_heartbeat_interval: "" # "" = leave unset multica_agent_timeout: "" # "" = leave unset ("0s" disables the cap) # Ansible owns the version: stop the CLI self-updating out from under the # role's declared state. Set false only if you want the daemon to self-update. multica_disable_auto_update: true # Boot autostart. On Linux `multica daemon autostart enable` writes a systemd # *user* unit, which only starts at boot when the user has lingering enabled. multica_autostart: true multica_enable_linger: true # ----------------------------------------------------------------------------- # Authentication — backend-agnostic by design # ----------------------------------------------------------------------------- # REQUIRED. A Multica personal access token: `mul_...` (user PAT) or # `mcn_...` (Cloud Node PAT). The role takes a VALUE; it does not know or care # where it came from. Supply it from the playbook with whatever your # environment already uses: # # HashiCorp Vault: # multica_pat: "{{ lookup('community.hashi_vault.vault_kv2_get', # 'multica/agent-host').secret.pat }}" # ansible-vault encrypted var: # multica_pat: "{{ vaulted_multica_pat }}" # 1Password: # multica_pat: "{{ lookup('community.general.onepassword', # 'Multica Agent Host PAT', field='credential') }}" # Environment: # multica_pat: "{{ lookup('env', 'MULTICA_PAT') }}" # # Consolidating secret providers later is a one-line playbook change; this role # is untouched by it. multica_pat: "" # Force `multica login --token` even when the host already reports an # authenticated session against multica_server_url. multica_force_relogin: false # ----------------------------------------------------------------------------- # Agent CLIs # ----------------------------------------------------------------------------- # Which provider CLIs this host should offer. Each must be a key in # multica_agent_cli_catalog. The daemon registers one runtime per CLI it finds. multica_agent_clis: - claude # Some agent CLIs are installed by piping a vendor script into a shell. That is # a real supply-chain decision, so it is opt-in and off by default. multica_allow_remote_install_scripts: false multica_agent_cli_catalog: claude: provider: claude # matches `provider` in `multica runtime list` binary: claude method: npm package: "@anthropic-ai/claude-code" # Pinned: npm "latest" is 2.1.306 while "stable" is 2.1.304, so an empty # value silently tracks whichever npm serves that day. 2.1.304 is the # version running on haunted-mansion. package_version: "2.1.304" version_command: "claude --version" # Subscription auth needs a browser once per host. Not automatable here. manual_login: true manual_login_hint: "run `claude` once as {{ multica_user }} and complete the login" hermes: provider: hermes binary: hermes method: script install_url: "https://hermes-agent.nousresearch.com/install.sh" install_dir: "{{ multica_user_home }}/.hermes/hermes-agent" version_command: "hermes --version" manual_login: true manual_login_hint: "configure Hermes credentials as {{ multica_user }} (Hermes reads 1Password natively; confirm against its docs)" # Keys MERGED (recursively) into the daemon user's ~/.claude/settings.json. # Merged, not templated: Claude Code writes that file itself. Keys not named # here are left alone. Empty = don't touch the file. # # An npm-installed Claude Code updates itself in place, which silently breaks # the package_version pin above (and the next play downgrades it again). # Setting env.DISABLE_AUTOUPDATER: "1" here is what makes the pin hold. multica_claude_settings: {} # ----------------------------------------------------------------------------- # Node.js (installed only when a selected agent CLI needs npm) # ----------------------------------------------------------------------------- # Full semver — this is a pin, not a major-version track. multica_node_version: "24.22.1" multica_node_dist_base_url: "https://nodejs.org/dist" multica_node_prefix: /usr/local/lib/nodejs # npm global prefix for the daemon user, so agent CLI installs need no root. multica_npm_prefix: "{{ multica_user_home }}/.npm-global" # ----------------------------------------------------------------------------- # Verification # ----------------------------------------------------------------------------- multica_verify: true # How long to wait for runtimes to appear online after the daemon starts. multica_verify_retries: 24 multica_verify_delay: 5