Account layout, homeserver reachability, and the target forms Apus accepts for Matrix rooms and users.

Profile management

apus matrix profile set --name "Apus Assistant"
apus matrix profile set --avatar-url https://cdn.example.org/avatar.png

Pass both options in one call. Matrix accepts mxc:// avatar URLs directly; passing http:///https:// uploads the file first and stores the resolved mxc:// URL into channels.matrix.avatarUrl (or the per-account override).

Direct room repair

If direct-message state drifts, Apus can end up with stale m.direct mappings pointing at old solo rooms instead of the live DM. Inspect the current mapping for a peer:

apus matrix direct inspect --user-id @alice:example.org

Repair it:

apus matrix direct repair --user-id @alice:example.org

Both commands accept --account <id> for multi-account setups. The repair flow:

It does not delete old rooms automatically. It picks the healthy DM and updates the mapping so future Matrix sends, verification notices, and other direct-message flows target the right room.

Mapping updates read the existing account data before writing. If that read fails, the update stops without replacing existing mappings. Retry the repair after account-data reads recover.

Multi-account

{
  channels: {
    matrix: {
      enabled: true,
      defaultAccount: "assistant",
      dm: { policy: "pairing" },
      accounts: {
        assistant: {
          homeserver: "https://matrix.example.org",
          accessToken: "syt_assistant_xxx",
          encryption: true,
        },
        alerts: {
          homeserver: "https://matrix.example.org",
          accessToken: "syt_alerts_xxx",
          dm: {
            policy: "allowlist",
            allowFrom: ["@ops:example.org"],
            threadReplies: "off",
          },
        },
      },
    },
  },
}

Inheritance:

Default account selection:

Promotion:

See Configuration reference for the shared multi-account pattern.

Private/LAN homeservers

By default, Apus blocks private/internal Matrix homeservers for SSRF protection unless you opt in per account.

If your homeserver runs on localhost, a LAN/Tailscale IP, or an internal hostname, enable network.dangerouslyAllowPrivateNetwork for that account:

{
  channels: {
    matrix: {
      homeserver: "http://matrix-synapse:8008",
      network: {
        dangerouslyAllowPrivateNetwork: true,
      },
      accessToken: "syt_internal_xxx",
    },
  },
}

CLI setup example:

apus matrix account add \
  --account ops \
  --homeserver http://matrix-synapse:8008 \
  --allow-private-network \
  --access-token syt_ops_xxx

This opt-in only allows trusted private/internal targets. Public cleartext homeservers such as http://matrix.example.org:8008 remain blocked. Prefer https:// whenever possible.

Proxying Matrix traffic

If your Matrix deployment needs an explicit outbound HTTP(S) proxy, set channels.matrix.proxy:

{
  channels: {
    matrix: {
      homeserver: "https://matrix.example.org",
      accessToken: "syt_bot_xxx",
      proxy: "http://127.0.0.1:7890",
    },
  },
}

Named accounts can override the top-level default with channels.matrix.accounts.<id>.proxy. Apus uses the same proxy setting for runtime Matrix traffic and account status checks.

Target resolution

Matrix accepts these target forms anywhere Apus asks for a room or user target:

Matrix room IDs are case-sensitive. Use the exact room ID casing from Matrix when configuring explicit delivery targets, cron jobs, bindings, or allowlists. Apus keeps internal session keys canonical for storage, so those lowercase keys are not a reliable source for Matrix delivery IDs.

Config-backed peer and group listings use the selected account's allowlists and configured rooms without loading stored Matrix credentials.

Live directory lookup uses the logged-in Matrix account: