Commit Graph
6 Commits
Author SHA1 Message Date
darmanandClaude Opus 5 a8a1cffa3e mars: mirror luna's Obsidian vault to disk with livesync-bridge
Gives the Hermes agent a real directory of markdown for the luna_wiki
vault, at /var/lib/livesync-bridge/vault and mounted into her container at
/opt/data/vault (inside HERMES_WRITE_SAFE_ROOT, so she can write, not only
read). Obsidian itself is an Electron GUI with no headless mode, and an
agent wants files rather than an app.

livesync-bridge is Deno, not packaged, and publishes no image — upstream
ships only a `build: .` compose file. So it comes in as a pinned non-flake
input and runs under systemd. Two things that are not obvious:

  - The source is COPIED to a fixed path rather than run from /nix/store.
    Deno keys localStorage — where the bridge records per-file sync state —
    by the main module's origin. Verified by running one source tree from
    two paths against a single DENO_DIR: two origin directories appear. Run
    from the store, every input bump would silently reset both peers to a
    full rescan.
  - It runs as uid 986/gid 983, the same identity the hermes container
    uses. Two uids in a shared group only works while every file stays
    group-writable, and one 0644 file dropped by the agent would stall sync
    on that path.

Talks to CouchDB over the tailnet (jupiter.orbit.sol:5984), so neptun's
vhost, its TLS and its path allowlist are all out of the picture.

Verified before deploying: `deno check` passes on nixpkgs' 2.8.3 (upstream
pins 2.6.9), and the bridge starts, reads LSB_CONFIG, detects a file and
writes its health heartbeat. Both directions confirmed working on mars
afterwards.

Credentials are currently the `obsidian` admin account and the personal
vault's passphrase, which means mars can decrypt every vault database and
not just luna's. Deliberate reuse of what existed; hosts/mars/secrets.nix
records the two independent ways to narrow it.

⚠️ Upstream has three open, unanswered issues on the storage->couchdb
direction (#50, #23, #46) and all fail silently — the log reports the
upload and the database is never updated. Do not treat this directory as
durable storage for anything luna cannot regenerate.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TLN5nkLBtCciD3ZnUwtw2b
2026-08-26 00:10:34 +02:00
darmanandClaude Opus 5 2a1a1628e1 relay: remove it; gitea already speaks Hermes's protocol
The relay existed on the premise that Gitea sends no header Hermes can read
an event name from, so something had to copy X-Gitea-Event into
X-GitHub-Event. That premise was wrong. Gitea's addDefaultHeaders sets

  req.Header["X-GitHub-Delivery"]   = []string{t.UUID}
  req.Header["X-GitHub-Event"]      = []string{event}
  req.Header["X-GitHub-Event-Type"] = []string{eventType}

unconditionally, for every webhook type, alongside X-Hub-Signature-256 in
GitHub's exact format. (Direct map assignment rather than .Add() specifically
to keep the "GitHub" casing that canonicalisation would destroy.) Hermes
validates that signature on any route without provider gating and reads the
event name from that header, so gitea and hermes already speak the same
protocol and the translation layer was translating nothing.

Gitea now posts straight at http://mars.orbit.sol:8644/webhooks/gitea-pr-comments.
The URL path is the Hermes route name, so a second subscription is a second
hook and nothing else -- the route-in-path indirection the relay grew was a
reimplementation of something Hermes already had.

Removes the module, the 200-line relay, its test, the mars import, the 8645
listener, and the stale gitea-hermes-webhook-relay.service entry left in the
secret's restartUnits. hermes-agent-webhook-route moves to
hosts/mars/hermes-agent.nix, next to the container and the read-only prompt
and filter mounts it depends on.

Also makes that unit refuse to subscribe when GITEA_HERMES_WEBHOOK_SECRET is
unset in the container, matching the existing empty-prompt check. An empty
secret silently fails every delivery signature check afterwards while the
unit still reports success -- the worst possible failure shape, and one this
setup can actually produce on a first deploy.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01S94o42aQ8VkBmEWvDem5xa
2026-08-23 08:09:01 +02:00
luna 806cec77e8 mars: add generic Gitea webhook relay 2026-08-23 01:45:18 +00:00
darmanandClaude Sonnet 5 dc83e8c156 add node_exporter host vitals + quickshell HUD
Prometheus node_exporter enabled on every host, plus a quickshell widget
(SUPER+CTRL+V on terra) to view live CPU/mem/disk/net/uptime without a
separate dashboard.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011FHr5ug9pu8q4XPrRkFnzJ
2026-08-22 20:50:16 +02:00
darmanandClaude Sonnet 5 99501ce7d2 mars: drop idle-timeout on the /mnt/jupiter cifs mount
podman-hermes-agent.service RequiresMountsFor /mnt/jupiter, but the mount
option copied from terra's (read-only, nothing depends on it) browsing
mount included x-systemd.idle-timeout=60 — confirmed on real hardware,
this killed the container ~60-70s after every start with no crash or
error, just an idle auto-unmount taking the dependent service down with
it. Keep the lazy x-systemd.automount (so boot doesn't stall if jupiter's
down) but drop the timeout now that something needs the mount to persist.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011FHr5ug9pu8q4XPrRkFnzJ
2026-08-22 03:09:21 +02:00
darmanandClaude Sonnet 5 7d63ba95df add mars host, move Hermes Agent there from jupiter
New on-site host mars runs Hermes Agent as its sole service: joins the
tailnet, mounts jupiter's samba share at /mnt/jupiter (doubling as
Hermes's shared dropbox), and hosts state locally under /var/lib/hermes.
Same Authentik OIDC app/Telegram bot as before, just relocated — neptun's
hermes.mgaction.town vhost now points at mars.orbit.sol instead of jupiter.

hosts/jupiter/hermes-agent.nix and its three sops secrets are removed;
jupiter's Caddy vhost for it is gone too. Also refreshes tailscale_authkey
across all hosts and fixes two stale "erik@laptop" keys in flake.nix's
kexec/installer-iso images (leftover from a previous laptop, already
swapped out of common.nix back in 2fd5752) to darman@terra.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011FHr5ug9pu8q4XPrRkFnzJ
2026-08-22 03:00:24 +02:00