feature/paperclip-ai #22

Merged
mixel merged 20 commits from feature/paperclip-ai into main 2026-06-30 17:08:47 +00:00
Owner
No description provided.
Add VM resource for PaperclipAI on tower (.253, ID 114, 2 vCPU / 4 GB / 32 GB),
register in inventory, expose ansible_inventory_yaml and ansible_ssh_keys_yaml
outputs required by the tofu:gen-inventory task.
Add site.yml play for tag_paperclip (ssh-hardening, firewall, swapfile,
services/paperclip). Fix missing become: true on the podman-host play.
Add host_vars with firewall port 3100, assh.yml SSH tunnel entry, and
implementation plan.
Enable podman-auto-update.timer so containers with AutoUpdate=registry
are kept current on all Podman hosts.
- Add lan_cidr global var (192.168.178.0/24) to group_vars/all so firewall
  defaults and other roles reference a single source of truth
- Add firewall_extra_allowed_cidrs and firewall_allowed_ports to util/firewall
- Add route allow (FORWARD chain) alongside INPUT allow for published container
  ports — netavark DNATs published ports so INPUT rules alone are never matched
- Add group_vars/tag_podman.yml allowing 10.88.0.0/13 so aardvark-dns on the
  bridge gateway is reachable from containers on all Podman hosts
- Move package installation into install.yml for clarity
- Add alvistack repo for up-to-date Podman packages on Debian
- Install aardvark-dns explicitly (required for container DNS with UFW)
- Add podman-tui v1.11.1 install with idempotent version check
- Enable podman.socket for TUI and API access
- Add podman-host tag to site.yml role entry
Adds firewall_extra_route_cidrs to the firewall role (UFW route/FORWARD
chain rules) and enables it for all Podman hosts so containers can reach
the internet via the host's NAT masquerade.
Move nfs_server, nfs_mount_options, sync_timer_on_calendar, and
sync_randomized_delay_sec into util/state-backup defaults so service
roles only need to specify what is genuinely service-specific (export
path, backup items, excludes). Removes the same five vars from hermes
and openclaw defaults and storage tasks.
Agents spawned inside the container were sandboxed from host tools and the
filesystem, causing bugs. Running paperclip directly on the host eliminates
the sandbox entirely. Postgres stays in a Podman quadlet, exposed to the host
on 127.0.0.1:5432.

- Replace paperclip.container/network quadlets with a systemd unit + env file
- Install Node.js 24 via NodeSource and paperclipai npm package globally
- Extract role tasks into sub-files (setup, nodejs, install, harnesses,
  postgres, service, backup) with main.yml as pure orchestrator
- Add quadlet_service_dir override to util/podman-quadlet to decouple template
  source directory from the systemd service name
- Wire state-backup for secrets and database backup directories
- Remove vault secrets that were redundant (JWT falls back to auth secret,
  master key is auto-generated by the app)
The hermes-signal daemon's receive stream went silent after signal-cli's
websocket to Signal's servers reconnected: 0.14.2 keeps emitting SSE
keepalives (which mask the gateway's stale-check) but stops delivering
messages. The gateway's client-side periodic SSE reconnect cannot recover
a wedged daemon receive loop - only a fixed daemon can.

- Bump signal-cli 0.14.2 -> 0.14.5, which fixes "receiving messages after
  a Signal server change". Restart hermes-signal when the binary is
  upgraded so the running daemon actually picks up the new version.
- signal-cli's native build now requires x86-64-v3, so bump the Hermes VM
  CPU type from x86-64-v2-AES to x86-64-v3. The host is a Ryzen 5800X3D
  (Zen 3, supports v3 but not v4/AVX-512) and the VM is pinned to it.
- Bump hermes-agent v2026.5.16 -> v2026.6.5, which carries the client-side
  SSE periodic-reconnect workaround referenced above.
The v2026.6.5 TUI ships without a committed package-lock.json, which broke
the build gate (it stat'd the lock as a hard requirement). Key off
package.json as the manifest instead, derive the build marker checksum
from the lockfile when present and fall back to package.json otherwise,
and split the npm step: `npm ci` when a lockfile exists, else `npm install
--package-lock=false`.
Ansible-core 2.21 deprecates apt_repository (removal in 2.25) and
community.mysql.* (removal in collection 6.0.0).

- Migrate apt_repository -> deb822_repository in the hermes, paperclip,
  openclaw and llamacpp roles. Each adds an explicit signed_by key,
  removes the legacy .list file so already-deployed hosts don't end up
  with duplicate repo definitions, and refreshes the apt cache only when
  the repo actually changes.
- Switch pelican-panel database tasks to ansible.mysql.* FQCNs and pin
  ansible.mysql in requirements.yml.
Default chrome-devtools-mcp to launching and reaping its own on-demand
headless Chromium on the VM instead of attaching to 127.0.0.1:9223, which
in practice was an ssh -R reverse tunnel to the operator's desktop Chrome.
This removes the desktop dependency so hermes can browse unattended, and
keeps RAM free on the constrained VM via lazy launch.

- defaults: browser_url defaults to "" (self-launch); add executable_path,
  headless, persistent user_data_dir, profile/state dirs and backup excludes
- validation: assert an executable path is set when in self-launch mode
- config + profile templates: branch between attach and self-launch
- host_vars/hermes: drop the 9223 browser_url, allow private/LAN URLs
Allow a host to deliberately trade the agent gateway's OS sandbox for full
machine access. Both toggles default to the secure posture and must be set
together to take effect: NoNewPrivileges blocks escalation regardless of
sudoers, so passwordless sudo only works once hardening is disabled.

- defaults: hermes_systemd_hardening (true) and hermes_sudo_nopasswd (false)
- sudo.yml: render/remove /etc/sudoers.d/hermes with visudo validation
- gateway unit templates: wrap the confinement directives in the toggle
- host_vars/hermes: opt this VM into full-machine access
Hermes only persists an "Always Approve" for /clear, /new, /reset, /undo by
flipping destructive_slash_confirm in its own config.yaml, which Ansible
re-renders every deploy — so a runtime opt-out reverts. Expose the key in
IaC (global default plus per-profile override) so an unattended Signal
profile like Ari can silence the prompt durably.

Also switch this host to smart approvals, letting the approval aux model
vet risky shell/execute_code commands instead of prompting on each.

- defaults: hermes_approvals_destructive_slash_confirm (true)
- config + profile templates: emit approvals.destructive_slash_confirm
- host_vars/hermes: approvals_mode=smart; Ari opts out of the confirm prompt
The approval entry paired provider: openai-codex with a deepseek-* model, an
invalid combination that failed and made hermes fall back to its built-in
nous/openrouter chain, which then errored with no-auth / no-credit. Run both
auxiliary tasks on deepseek-v4-flash: cheap, fast, and on the backend that
already holds a valid API key.
Tasks that become_user: hermes otherwise let Ansible create the remote_tmp
dir itself, emitting a "created with a mode of 0700 ... may cause issues when
running as another user" warning. Pre-create it owned by hermes so the dir
already exists; /tmp is volatile so this runs every deploy and is idempotent.
Add a SKILL.md to each services/<name>/ dir capturing that service's host,
IP, systemd units, ports, and ready-to-run read-only debug commands, and
document in AGENTS.md the encouraged on-host debugging workflow (SSH read-only
diagnostics, sudo -u <service_user> for owned files) plus which task commands
are pre-approved vs denied for consent.
mixel merged commit 2f034c6f9a into main 2026-06-30 17:08:47 +00:00
mixel deleted branch feature/paperclip-ai 2026-06-30 17:08:47 +00:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
mixel/infrastructure!22
No description provided.