콘텐츠로 이동

Matrix, Mattermost, Nextcloud Talk

Matrix E2EE를 포함한 자체 호스팅 워크스페이스 채팅 플랫폼.

이 페이지는 Revka의 세 가지 자체 호스팅 워크스페이스 채팅 채널인 Matrix(종단 간 암호화 룸 포함), Mattermost, Nextcloud Talk에 대한 레퍼런스입니다. 세 채널 모두 에이전트의 대화 기록을 귀하가 관리하는 인프라 내에 보관하므로, 프라이빗하거나 규제 환경에 있거나 에어갭 배포에 적합합니다. 정확한 설정 키, 전달 동작, 빌드 요구 사항, 웹훅 서명 계약이 필요할 때 이 페이지를 참고하십시오. 단계별 설정은 Mattermost 및 Nextcloud Talk 설정Telegram 및 Matrix 설정을 참조하십시오.

세 채널 모두 ~/.revka/config.toml[channels_config] 아래에서 구성합니다. 파일을 직접 편집하거나 revka onboard --channels-only를 실행한 뒤 데몬을 재시작하여 변경 사항을 적용하십시오. 모든 채널이 공유하는 트레이트 모델, 전달 모드, 허용 목록 시맨틱스는 채널 개요를 참조하십시오.

채널수신 방식공개 인바운드 포트 필요 여부빌드 기능 플래그
Matrixsync API (E2EE)아니요channel-matrix
MattermostREST v4 폴링아니요
Nextcloud Talk웹훅 (푸시)

세 채널 중 빌드 시점에 기능 게이팅이 적용되는 것은 Matrix뿐입니다. Mattermost와 Nextcloud Talk는 항상 컴파일에 포함됩니다.

Matrix 채널은 matrix-sdk를 통해 Matrix 클라이언트-서버 API를 사용합니다. 암호화된 룸에 대한 종단 간 암호화(E2EE), 다중 허용 룸, 룸 별칭 해석, 초안 스트리밍, 다중 메시지 문단 전달, 오디오 첨부 파일의 음성 전사, 일회성 키(OTK) 충돌 감지, 서버 측 키 백업에서의 교차 서명 복구를 지원합니다.

[channels_config.matrix]
homeserver = "https://matrix.example.com"
access_token = "syt_..."
user_id = "@revka:matrix.example.com"
device_id = "DEVICEID123"
room_id = "!room:matrix.example.com"
allowed_rooms = []
allowed_users = ["*"]
stream_mode = "partial" # off | partial | multi_message
draft_update_interval_ms = 1500
multi_message_delay_ms = 800
recovery_key = "" # optional: cross-signing recovery
필드타입기본값설명
homeserverstring홈서버 기본 URL. 필수.
access_tokenstring봇 계정 액세스 토큰. 필수.
user_idstring봇 Matrix ID(@name:server). E2EE 세션 복원을 위해 권장.
device_idstring안정적인 디바이스 식별자. E2EE에 권장; 없으면 재시작마다 새 디바이스가 등록되어 키 공유가 중단됩니다.
room_idstring기본 룸. 정규 ID(!room:server)를 권장하며, 별칭(#name:server)은 런타임에 해석됩니다.
allowed_roomsarray[]비어 있지 않으면 봇이 메시지를 수락하는 룸 ID/별칭의 전체 집합입니다(단일 룸 필터를 대체하며, 기본 room_id도 계속 수락하려면 여기에 포함해야 합니다). 비어 있으면(기본값) 구성된 room_id에서만 수신합니다.
allowed_usersarray상호작용을 허용할 Matrix 사용자 ID. []는 모두 거부, ["*"]는 모두 허용.
stream_modestring"off", "partial"(m.replace를 통한 초안 실시간 편집), 또는 "multi_message"(문단 분할).
draft_update_interval_msnumber1500초안 스트리밍의 편집 스로틀. E2EE 오버헤드를 흡수하기 위해 다른 채널보다 높게 설정됩니다.
multi_message_delay_msnumber800multi_message 모드에서 문단 청크 간 지연 시간.
recovery_keystring서버 백업에서 룸 키를 복원하기 위한 교차 서명 복구 키.
transcription.*table오디오 첨부 파일의 음성-텍스트 변환. 음성, TTS 및 전사를 참조하십시오.

Matrix 채널은 공개 인바운드 포트가 필요하지 않습니다. 홈서버에 아웃바운드로 연결하여 sync API를 통해 메시지를 수신합니다.

E2EE는 matrix-sdk를 통해 투명하게 처리됩니다. 봇의 디바이스에 룸 키가 있는 경우 별도 설정 없이 암호화된 룸에서 복호화 및 응답이 이루어집니다. 안정적인 암호화 동작을 위해 다음을 권장합니다.

  • 안정적인 device_id를 설정하십시오. 디바이스 ID가 변경되면 재시작마다 새 디바이스 등록이 강제되어 기존 키 공유 및 디바이스 검증이 중단됩니다. /_matrix/client/v3/account/whoami, 비밀번호 로그인, 또는 Element의 설정 → 세션에서 값을 확인할 수 있습니다.
  • user_id를 설정하여 재시작 후에도 아이덴티티가 유지되도록 하십시오.
  • recovery_key를 설정하여 암호화 스토어 초기화, 신규 설치, 또는 디바이스 초기화 후 서버 측 백업에서 룸 키와 교차 서명 시크릿이 자동으로 복원되도록 하십시오. 복원에 성공하면 Revka는 Matrix E2EE recovery successful을 로그에 기록합니다.

로컬 암호화 스토어는 ~/.revka/state/matrix/에 위치합니다. 홈서버에서 디바이스를 등록 해제하지 않고 삭제하면 오래된 디바이스로 인해 OTK 업로드 충돌이 발생합니다.

”연결됐지만 응답 없음” 체크리스트

섹션 제목: “”연결됐지만 응답 없음” 체크리스트”

Matrix에서 가장 흔한 증상은 “설정은 올바르고 확인도 통과했지만 봇이 응답하지 않는다”는 것입니다. 다음 순서로 확인하십시오.

  1. 발신자가 allowed_users에 의해 허용되어 있는지 확인합니다(테스트 시 ["*"] 사용 — []는 모두 거부).
  2. 봇 계정이 대상 룸에 실제로 입장했는지 확인합니다.
  3. access_token이 동일한 봇 계정 소유인지 확인합니다(whoami 검사).
  4. E2EE 룸의 경우 봇 디바이스가 신뢰할 수 있는 디바이스로부터 룸 키를 수신했는지 확인합니다.
  5. 설정 변경 후 데몬을 재시작했는지 확인합니다.

E2EE 진단을 위해 채널의 로그 레벨을 높이십시오.

Terminal window
RUST_LOG=revka::channels::matrix=debug revka daemon

SDK 수준 암호화 세부 정보를 보려면 matrix_sdk_crypto=debug를 추가하십시오.

Mattermost 채널은 봇 액세스 토큰으로 Mattermost REST API v4를 폴링합니다. 공개 인바운드 포트가 필요 없습니다. 스레드 답장, 멘션 전용 필터링, 타이핑 인디케이터, 오디오 첨부 파일의 음성 전사(25 MB 제한)를 지원합니다.

[channels_config.mattermost]
url = "https://mm.example.com"
bot_token = "mattermost-token"
channel_id = "channel-id"
allowed_users = ["*"]
thread_replies = true
mention_only = false
필드타입기본값설명
urlstringMattermost 서버의 기본 URL. 필수.
bot_tokenstring봇 계정 개인 액세스 토큰. 필수.
channel_idstring수신할 채널. 리슨 모드에서 필수; 생략하면 접근 가능한 모든 채널에서 수신.
allowed_usersarray상호작용을 허용할 Mattermost 사용자 ID. []는 모두 거부, ["*"]는 모두 허용.
thread_repliesbooltrue최상위 메시지에 스레드로 답장.
mention_onlyboolfalsetrue이면 봇을 @ 멘션한 메시지만 처리.
proxy_urlstring선택적 채널별 HTTP/SOCKS5 프록시.
transcription.*table오디오 첨부 파일의 음성-텍스트 변환(25 MB 제한).
  • 사용자가 기존 스레드 내에서 답장하면 Revka는 항상 같은 스레드에 답장합니다.
  • thread_replies = true(기본값)이면 Revka는 최상위 메시지에 스레드로 답장합니다. thread_replies = false이면 채널 루트에 답장합니다.
  • mention_only = true이면 Revka는 allowed_users 검사 이후 추가 필터를 적용합니다. 봇을 명시적으로 @bot_username 멘션하지 않은 메시지는 무시되며, 멘션 토큰은 모델에 전달되기 전에 제거됩니다. 이는 바쁜 공유 채널에서 불필요한 모델 호출을 줄이는 데 유용합니다.

폴링은 재시도 백오프가 적용된 속도 제한이 있습니다. 봇 계정 생성 및 채널 ID 확인 방법은 Mattermost 및 Nextcloud Talk 설정을 참조하십시오.

Nextcloud Talk 채널은 웹훅 모드로 동작합니다. Nextcloud가 각 룸 이벤트를 게이트웨이의 POST /nextcloud-talk으로 푸시하면, Revka는 서명을 검증하고 에이전트를 실행한 뒤 Nextcloud Talk OCS API를 통해 응답합니다. Nextcloud가 게이트웨이에 접근해야 하므로 공개 HTTPS URL이 필요합니다. 터널로 게이트웨이 노출하기를 참조하십시오.

[channels_config.nextcloud_talk]
base_url = "https://cloud.example.com"
app_token = "nextcloud-talk-app-token"
bot_name = "revka"
webhook_secret = "optional-webhook-secret"
allowed_users = ["*"]
필드타입기본값설명
base_urlstringNextcloud 인스턴스 URL. 필수. 끝에 슬래시가 있으면 자동으로 제거됩니다.
app_tokenstring아웃바운드 OCS 답장 시 Authorization: Bearer <token>으로 전송되는 봇 앱 토큰. 필수.
bot_namestring봇의 Talk 표시 이름. 셀프 에코 방지에 사용됩니다(아래 참조). 설정하지 않으면 빈 문자열이 기본값이 되지만, 리터럴 이름 revka는 이 설정에 관계없이 하드코딩된 검사를 통해 항상 봇으로 처리됩니다.
webhook_secretstring인바운드 웹훅 서명 검증을 위한 공유 HMAC 시크릿. 권장. REVKA_NEXTCLOUD_TALK_WEBHOOK_SECRET 환경 변수로 덮어쓸 수 있습니다.
allowed_usersarray허용할 Nextcloud 액터 ID. []는 모두 거부, ["*"]는 모두 허용. users/ 또는 bots/ 접두사를 제거한 후 매칭됩니다.
proxy_urlstring선택적 채널별 HTTP/SOCKS5 프록시.

Nextcloud Talk 봇의 웹훅 URL을 게이트웨이 인그레스 경로로 지정하십시오. 게이트웨이는 시작 시 해당 라우트를 로그에 기록합니다(POST /nextcloud-talk — Nextcloud Talk bot webhook).

POST /nextcloud-talk
Content-Type: application/json
X-Nextcloud-Talk-Random: <random-seed>
X-Nextcloud-Talk-Signature: <hmac-hex>

이 엔드포인트는 베어러 토큰을 사용하지 않으며 서명으로 인증됩니다(아래 참조).

응답발생 조건
404[channels_config.nextcloud_talk]가 구성되지 않은 경우.
400요청 본문이 유효한 JSON이 아닌 경우.
401서명 검증 실패(시크릿이 설정된 경우에만 확인).
200수락됨. 페이로드에 처리 가능한 사용자 메시지가 없는 경우에도 반환됨 — 봇, 시스템, Note가 아닌 이벤트, 허용되지 않은 이벤트는 자동으로 확인 응답됩니다.

아웃바운드 답장은 웹훅 페이로드의 Talk 룸으로 OCS 채팅 API를 통해 전송됩니다.

POST <base_url>/ocs/v2.php/apps/spreed/api/v1/chat/<room-token>?format=json
Authorization: Bearer <app_token>
OCS-APIRequest: true

Revka는 현재 Nextcloud Talk 봇이 전송하는 Activity Streams 2.0 Create 페이로드와 레거시 message 형식을 모두 파싱하며, 밀리초 및 초 단위 타임스탬프를 모두 정규화합니다.

웹훅 봇은 자신의 답장이 새 룸 이벤트로 에코되어 에이전트가 스스로 영원히 답장하는 피드백 루프를 일으킬 수 있습니다. Revka는 자체 발신 이벤트가 모델에 도달하기 전에 제거합니다.

  • 액터 타입이 bots 또는 application인 이벤트는 무시됩니다.
  • 액터 ID에 bots/ 접두사가 있는 이벤트는 무시됩니다.
  • 액터 이름이 구성된 bot_name과 일치하는(대소문자 무시) 이벤트는 무시됩니다. 리터럴 이름 revka는 다른 bot_name을 설정한 경우에도 항상 봇으로 처리됩니다.

이름 검사는 안전망 역할을 합니다. Nextcloud는 봇이 보낸 메시지에 대해 액터 타입을 항상 신뢰할 수 있게 설정하지 않으므로, bot_name으로 매칭하면 타입 검사를 통과하는 에코를 잡을 수 있습니다. bot_name을 봇의 정확한 Talk 표시 이름으로 설정하십시오.

Nextcloud Talk 웹훅은 세 채널 중 유일한 인그레스 엔드포인트입니다(Matrix와 Mattermost는 아웃바운드 연결 방식이므로 서명할 인바운드 웹훅이 없습니다). webhook_secret이 구성된 경우, POST /nextcloud-talk로 들어오는 모든 요청은 HMAC-SHA256 서명으로 인증됩니다.

Revka는 두 헤더를 읽고 다음을 계산합니다.

hex( hmac_sha256( secret, X-Nextcloud-Talk-Random + raw_request_body ) )

결과는 X-Nextcloud-Talk-Signature 헤더와 상수 시간 비교됩니다. 주요 사항:

  • HMAC는 랜덤 시드 뒤에 원시 요청 본문을 연결한 값을 대상으로 합니다 — 재직렬화된 JSON 객체가 아닙니다. Nextcloud와 게이트웨이 사이에서 프록시가 본문을 재작성하거나 재포맷하지 않도록 하십시오. 그렇지 않으면 검증이 실패합니다.
  • 서명 헤더에 sha256= 접두사가 있으면 수락 후 제거됩니다.
  • X-Nextcloud-Talk-Random 헤더가 없거나, 서명이 잘못된 형식이거나(유효한 16진수가 아님), 다이제스트가 일치하지 않으면 게이트웨이는 401 Invalid signature를 반환합니다.

시크릿은 설정 파일 또는 환경 변수에서 가져올 수 있으며, 환경 변수가 우선합니다.

Terminal window
export REVKA_NEXTCLOUD_TALK_WEBHOOK_SECRET="your-webhook-secret"

우선 순위:

  1. REVKA_NEXTCLOUD_TALK_WEBHOOK_SECRET(환경 변수) — 설정되어 있고 비어 있지 않으면 사용.
  2. [channels_config.nextcloud_talk] 아래의 webhook_secret — 그 외의 경우 사용.

환경 변수를 사용하면 시크릿을 config.toml에서 제외할 수 있습니다. Nextcloud Talk 봇에도 동일한 시크릿을 설정해야 양쪽에서 동일한 HMAC가 계산됩니다. 게이트웨이 인그레스 엔드포인트 전체와 서명 규칙은 웹훅 인그레스를 참조하십시오.

Matrix 지원은 matrix-sdk 의존성을 가져오는 Cargo 기능 channel-matrix 뒤에 컴파일됩니다. 이는 기본 Cargo 기능이 아니므로 cargo buildcargo install만 실행하면 Matrix가 제외됩니다. 공식 릴리스 바이너리는 릴리스 파이프라인에서 --features channel-matrix를 명시적으로 지정하여 빌드하므로 Matrix가 포함됩니다. 직접 빌드하려면 다음을 실행하십시오.

Terminal window
cargo build --release --features channel-matrix

--no-default-features와 직접 선택한 기능 목록으로 빌드하는 경우, Matrix가 필요하면 channel-matrix를 다시 추가하십시오. Mattermost와 Nextcloud Talk는 기능 플래그가 없으며 항상 사용 가능합니다. 채널 기능 플래그 전체 목록(Matrix, Lark, Nostr, WhatsApp Web, Voice Wake)은 Cargo 기능 플래그 및 ADR을 참조하십시오.

세 채널 모두 allowed_users로 인바운드 발신자를 제한합니다.

  • 빈 목록([])은 모든 발신자를 거부합니다.
  • "*" 단일 항목은 모든 발신자를 허용합니다.
  • 그 외에는 목록에 있는 ID만 수락됩니다 — 각각 Matrix 사용자 ID, Mattermost 사용자 ID, Nextcloud 액터 ID.

전달 여부를 확인할 때는 allowed_users = ["*"]로 시작한 뒤 명시적 ID로 제한하십시오. Nextcloud Talk의 경우 액터 ID는 users/ / bots/ 접두사를 제거한 후 매칭됩니다.