docs: Simplify XMPP integration - replace detailed Prosody/Ejabberd configs with standard XEP-0363 info

This commit is contained in:
2025-11-26 20:27:04 +01:00
parent 40d741967a
commit 90870d90e4

334
README.md
View File

@@ -185,8 +185,7 @@ Test Coverage:
- [Podman Deployment](#podman-deployment)
- [Nginx Reverse Proxy](#nginx-reverse-proxy)
- [Apache2 Reverse Proxy](#apache2-reverse-proxy)
- [Prosody XMPP Integration](#prosody-xmpp-integration)
- [Ejabberd XMPP Integration](#ejabberd-xmpp-integration)
- [XMPP Server Integration](#xmpp-server-integration)
- [XEP-0363 Implementation](#xep-0363-implementation)
- [API Versions (V1, V2, V3)](#api-versions)
@@ -1521,334 +1520,27 @@ server {
---
## Prosody XMPP Integration
## XMPP Server Integration
### Prosody Configuration
```lua
-- /etc/prosody/prosody.cfg.lua
-- HMAC File Server integration for XEP-0363
HMAC File Server implements the standard **XEP-0363: HTTP File Upload** protocol and works out-of-the-box with all XMPP servers including Prosody, Ejabberd, Openfire, and others.
-- Enable HTTP file upload module
modules_enabled = {
-- Core modules
"roster";
"saslauth";
"tls";
"dialback";
"disco";
"carbons";
"pep";
"private";
"blocklist";
"vcard4";
"vcard_legacy";
"version";
"uptime";
"time";
"ping";
"admin_adhoc";
### Quick Setup
-- HTTP file upload
"http_upload_external";
}
Configure your XMPP server's `http_upload_external` module to point to your HMAC File Server:
-- VirtualHost configuration
VirtualHost "example.com"
enabled = true
-- SSL configuration
ssl = {
key = "/etc/prosody/certs/example.com.key";
certificate = "/etc/prosody/certs/example.com.crt";
}
-- HTTP file upload configuration
http_upload_external_base_url = "https://files.example.com"
http_upload_external_secret = "your-very-secret-hmac-key"
http_upload_external_file_size_limit = 10737418240 -- 10GB
http_upload_external_quota = 1073741824000 -- 1TB per user
-- Custom upload URL patterns (for HMAC File Server)
http_upload_external_put_url = "https://files.example.com/upload/{filename}"
http_upload_external_get_url = "https://files.example.com/download/{filename}"
-- Component for file upload service
Component "upload.example.com" "http_upload_external"
http_upload_external_base_url = "https://files.example.com"
http_upload_external_secret = "your-very-secret-hmac-key"
http_upload_external_file_size_limit = 10737418240
-- Logging
log = {
info = "/var/log/prosody/prosody.log";
error = "/var/log/prosody/prosody.err";
"*syslog";
}
```
### Prosody Module Configuration
```lua
-- /usr/lib/prosody/modules/mod_http_upload_external.lua
-- Custom module for HMAC File Server integration
local hmac_sha256 = require "util.hashes".hmac_sha256;
local base64 = require "util.encodings".base64;
local uuid = require "util.uuid".generate;
local http = require "net.http";
module:depends("disco");
local external_base_url = module:get_option_string("http_upload_external_base_url");
local external_secret = module:get_option_string("http_upload_external_secret");
local file_size_limit = module:get_option_number("http_upload_external_file_size_limit", 100*1024*1024);
local quota = module:get_option_number("http_upload_external_quota", 1024*1024*1024);
-- XEP-0363 disco feature
module:add_feature("urn:xmpp:http:upload:0");
-- Handle upload requests
function handle_upload_request(event)
local stanza = event.stanza;
local filename = stanza:get_child_text("filename", "urn:xmpp:http:upload:0");
local filesize = tonumber(stanza:get_child_text("size", "urn:xmpp:http:upload:0"));
local content_type = stanza:get_child_text("content-type", "urn:xmpp:http:upload:0") or "application/octet-stream";
if not filename or not filesize then
return st.error_reply(stanza, "modify", "bad-request", "Missing filename or size");
end
if filesize > file_size_limit then
return st.error_reply(stanza, "modify", "not-acceptable", "File too large");
end
-- Generate HMAC authentication
local timestamp = os.time();
local upload_id = uuid();
local message = filename .. filesize .. timestamp .. upload_id;
local signature = base64.encode(hmac_sha256(external_secret, message));
-- Construct URLs
local put_url = string.format("%s/upload?filename=%s&timestamp=%d&uploadid=%s&signature=%s",
external_base_url,
filename,
timestamp,
upload_id,
signature
);
local get_url = string.format("%s/download/%s", external_base_url, filename);
-- Return slot
local reply = st.reply(stanza)
:tag("slot", {xmlns="urn:xmpp:http:upload:0"})
:tag("put", {url=put_url}):up()
:tag("get", {url=get_url}):up()
:up();
return reply;
end
module:hook("iq-get/host/urn:xmpp:http:upload:0:request", handle_upload_request);
```
---
## Ejabberd XMPP Integration
### Ejabberd Configuration
```yaml
# /etc/ejabberd/ejabberd.yml
# HMAC File Server integration
hosts:
- "example.com"
listen:
-
port: 5222
ip: "::"
module: ejabberd_c2s
starttls: true
certfile: "/etc/ejabberd/certs/example.com.pem"
-
port: 5269
ip: "::"
module: ejabberd_s2s_in
-
port: 5443
ip: "::"
module: ejabberd_http
tls: true
certfile: "/etc/ejabberd/certs/example.com.pem"
request_handlers:
"/upload": mod_http_upload
"/admin": ejabberd_web_admin
"/api": mod_http_api
modules:
mod_adhoc: {}
mod_admin_extra: {}
mod_announce: {}
mod_avatar: {}
mod_blocking: {}
mod_bosh: {}
mod_caps: {}
mod_carboncopy: {}
mod_client_state: {}
mod_configure: {}
mod_disco: {}
mod_fail2ban: {}
mod_http_api: {}
mod_http_upload:
put_url: "https://files.example.com/upload"
get_url: "https://files.example.com/download"
external_secret: "your-very-secret-hmac-key"
max_size: 10737418240 # 10GB
thumbnail: false
custom_headers:
"Access-Control-Allow-Origin": "*"
"Access-Control-Allow-Methods": "GET,HEAD,PUT,OPTIONS"
"Access-Control-Allow-Headers": "Content-Type"
mod_last: {}
mod_mam: {}
mod_mqtt: {}
mod_muc: {}
mod_muc_admin: {}
mod_offline: {}
mod_ping: {}
mod_privacy: {}
mod_private: {}
mod_proxy65: {}
mod_pubsub: {}
mod_push: {}
mod_register: {}
mod_roster: {}
mod_shared_roster: {}
mod_stats: {}
mod_time: {}
mod_vcard: {}
mod_version: {}
# Authentication
auth_method: internal
# Database
default_db: mnesia
# Access rules
access_rules:
local:
- allow: local
c2s:
- deny: blocked
- allow
announce:
- allow: admin
configure:
- allow: admin
muc_create:
- allow: local
pubsub_createnode:
- allow: local
register:
- allow
trusted_network:
- allow: loopback
# ACL
acl:
local:
user_regexp: ""
loopback:
ip:
- "127.0.0.0/8"
- "::1/128"
- "::FFFF:127.0.0.1/128"
admin:
user:
- "admin@example.com"
# Logging
loglevel: 4
log_rotate_size: 10485760
log_rotate_count: 5
# Standard XEP-0363 configuration (works with any XMPP server)
http_upload_external:
base_url: "https://files.example.com"
secret: "your-shared-hmac-secret"
max_file_size: 10737418240 # 10GB
```
### Custom Ejabberd HTTP Upload Module
```erlang
% /opt/ejabberd/lib/ejabberd-23.01/ebin/mod_http_upload_external.erl
% Custom module for HMAC File Server integration
The server handles all the HMAC authentication and file management automatically. No custom modules required.
-module(mod_http_upload_external).
-author('admin@example.com').
### Experimental Custom Modules
-behaviour(gen_mod).
-export([start/2, stop/1, process_iq/1, mod_opt_type/1, mod_options/1]).
-include("ejabberd.hrl").
-include("logger.hrl").
-include("xmpp.hrl").
start(Host, Opts) ->
gen_iq_handler:add_iq_handler(ejabberd_local, Host,
?NS_HTTP_UPLOAD_0, ?MODULE,
process_iq).
stop(Host) ->
gen_iq_handler:remove_iq_handler(ejabberd_local, Host, ?NS_HTTP_UPLOAD_0).
process_iq(#iq{type = get, sub_els = [#upload_request{filename = Filename,
size = Size,
'content-type' = ContentType}]} = IQ) ->
Host = ejabberd_config:get_myname(),
% Get configuration
PutURL = gen_mod:get_module_opt(Host, ?MODULE, put_url),
GetURL = gen_mod:get_module_opt(Host, ?MODULE, get_url),
Secret = gen_mod:get_module_opt(Host, ?MODULE, external_secret),
MaxSize = gen_mod:get_module_opt(Host, ?MODULE, max_size),
% Validate file size
case Size =< MaxSize of
true ->
% Generate HMAC signature
Timestamp = erlang:system_time(second),
UploadId = uuid:uuid_to_string(uuid:get_v4()),
Message = <<Filename/binary, (integer_to_binary(Size))/binary,
(integer_to_binary(Timestamp))/binary, UploadId/binary>>,
Signature = base64:encode(crypto:mac(hmac, sha256, Secret, Message)),
% Construct URLs
PutURLFinal = <<PutURL/binary, "?filename=", Filename/binary,
"&timestamp=", (integer_to_binary(Timestamp))/binary,
"&uploadid=", UploadId/binary,
"&signature=", Signature/binary>>,
GetURLFinal = <<GetURL/binary, "/", Filename/binary>>,
% Return slot
Slot = #upload_slot{get = GetURLFinal, put = PutURLFinal},
xmpp:make_iq_result(IQ, Slot);
false ->
xmpp:make_error(IQ, xmpp:err_not_acceptable(<<"File too large">>, ?MYLANG))
end;
process_iq(IQ) ->
xmpp:make_error(IQ, xmpp:err_bad_request()).
mod_opt_type(put_url) -> fun iolist_to_binary/1;
mod_opt_type(get_url) -> fun iolist_to_binary/1;
mod_opt_type(external_secret) -> fun iolist_to_binary/1;
mod_opt_type(max_size) -> fun(I) when is_integer(I), I > 0 -> I end.
mod_options(_Host) ->
[{put_url, <<"">>},
{get_url, <<"">>},
{external_secret, <<"">>},
{max_size, 104857600}].
```
Advanced users can explore experimental Prosody and Ejabberd modules in the `ejabberd-module/` directory. These are **development stage** and require additional testing. The standard XEP-0363 implementation is recommended for production use.
---