Jingle A/V (XEP-0166/0167/0176) needs a STUN/TURN server for NAT traversal. Add coturn and advertise it to clients via XEP-0215. - coturn container, host networking (a relay needs its full UDP port range reachable, and Docker NAT hides the peer addresses coturn needs). - mod_turn_external in Prosody to advertise the service and mint time-limited credentials from a shared secret. - Advertise UDP and TCP transports plus turns: on 5349, so clients on UDP-blocking networks can still connect. - Deny relaying to private ranges, so this is not an open proxy into internal services. TURN host is guschin.info rather than turn.guschin.info because only the former is in the certificate SANs and turns: clients validate the name. TURN_HOST/TURN_SECRET go in .env, which is gitignored and set per deployment; TURN_SECRET must match static-auth-secret in turnserver.conf. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
151 lines
4.4 KiB
Lua
151 lines
4.4 KiB
Lua
-- Prosody XMPP Server Configuration
|
|
-- Domain: xmpp.guschin.info
|
|
|
|
admins = { "admin@guschin.info", "admin@xmpp.guschin.info" }
|
|
|
|
plugin_paths = { "/usr/lib/prosody/modules" }
|
|
|
|
modules_enabled = {
|
|
-- Generally required
|
|
"roster";
|
|
"saslauth";
|
|
"tls";
|
|
"dialback";
|
|
"disco";
|
|
|
|
-- Not essential, but recommended
|
|
"carbons";
|
|
"pep";
|
|
"private";
|
|
"vcard";
|
|
"version";
|
|
"uptime";
|
|
"time";
|
|
"ping";
|
|
"register";
|
|
"mam";
|
|
|
|
-- Admin interface
|
|
"admin_adhoc";
|
|
|
|
-- Gateway support
|
|
"privilege";
|
|
"http_file_share";
|
|
|
|
-- Audio/video calls (Jingle): advertise the TURN/STUN server to clients
|
|
-- via XEP-0215. Clients do the media themselves; Prosody only signals
|
|
-- and hands out time-limited TURN credentials.
|
|
"turn_external";
|
|
};
|
|
|
|
modules_disabled = {
|
|
-- "offline";
|
|
"posix"; -- Disable posix module to avoid threading issues in Docker
|
|
};
|
|
|
|
-- Logging configuration
|
|
log = {
|
|
info = "/var/log/prosody/prosody.log";
|
|
error = "/var/log/prosody/prosody.err";
|
|
};
|
|
|
|
-- Storage configuration for MySQL
|
|
storage = "sql"
|
|
sql = {
|
|
driver = "MySQL";
|
|
database = os.getenv("MYSQL_DATABASE") or "prosody";
|
|
username = os.getenv("MYSQL_USER") or "prosody";
|
|
password = os.getenv("MYSQL_PASSWORD") or "prosodypass";
|
|
host = os.getenv("MYSQL_HOST") or "localhost";
|
|
port = 3306;
|
|
}
|
|
|
|
-- Port configuration (global section)
|
|
c2s_ports = { 5222 }
|
|
s2s_ports = { 5269 }
|
|
component_ports = { 5347 }
|
|
component_interface = "0.0.0.0"
|
|
http_ports = { 5280 }
|
|
https_ports = { 5281 }
|
|
|
|
-- Require TLS on c2s/s2s connections
|
|
c2s_require_encryption = true
|
|
s2s_require_encryption = true
|
|
|
|
-- Authentication
|
|
authentication = "internal_plain"
|
|
|
|
-- Message archive settings
|
|
archive_expires_after = "never"
|
|
|
|
-- Certificates directory (global, before VirtualHost)
|
|
certificates = "/etc/prosody/certs"
|
|
|
|
-- TURN/STUN for audio/video calls (XEP-0215 External Service Discovery).
|
|
-- mod_turn_external does not run a relay itself; it tells clients where the
|
|
-- coturn instance is and issues short-lived credentials signed with the
|
|
-- shared secret. turn_external_secret must equal static-auth-secret in
|
|
-- coturn/turnserver.conf.
|
|
--
|
|
-- turn_external_host is guschin.info rather than turn.guschin.info because
|
|
-- only the former is in the certificate SANs, and turns:// (TLS) clients
|
|
-- validate the name against the cert.
|
|
turn_external_host = os.getenv("TURN_HOST") or "guschin.info"
|
|
turn_external_secret = os.getenv("TURN_SECRET")
|
|
turn_external_port = 3478
|
|
turn_external_tls_port = 5349
|
|
turn_external_ttl = 86400
|
|
-- Also advertise TCP transports, not just UDP: some restrictive networks
|
|
-- block UDP entirely, and TCP/TLS on 5349 is the fallback that still works.
|
|
turn_external_tcp = true
|
|
|
|
-- Primary virtual host (user@guschin.info)
|
|
VirtualHost "guschin.info"
|
|
ssl = {
|
|
key = "/etc/prosody/certs/guschin.info.key";
|
|
certificate = "/etc/prosody/certs/guschin.info.crt";
|
|
}
|
|
privileged_entities = {
|
|
["telegram.guschin.info"] = {
|
|
roster = "both"; -- auto add/remove Telegram contacts from roster
|
|
message = "outgoing"; -- reflect messages sent via official Telegram apps
|
|
iq = {
|
|
["http://jabber.org/protocol/pubsub"] = "both"; -- PEP bookmarks
|
|
["http://jabber.org/protocol/pubsub#owner"] = "set"; -- message display sync
|
|
["urn:xmpp:http:upload:0"] = "get"; -- upload on behalf of users
|
|
};
|
|
};
|
|
}
|
|
|
|
-- Secondary virtual host (user@xmpp.guschin.info)
|
|
VirtualHost "xmpp.guschin.info"
|
|
ssl = {
|
|
key = "/etc/prosody/certs/guschin.info.key";
|
|
certificate = "/etc/prosody/certs/guschin.info.crt";
|
|
}
|
|
|
|
-- Component for MUC (Multi-User Chat)
|
|
Component "muc.guschin.info" "muc"
|
|
modules_enabled = { "muc_mam" }
|
|
storage = "sql"
|
|
ssl = {
|
|
key = "/etc/prosody/certs/guschin.info.key";
|
|
certificate = "/etc/prosody/certs/guschin.info.crt";
|
|
}
|
|
|
|
-- HTTP file upload (XEP-0363) — used by slidgram for Telegram→XMPP attachments
|
|
Component "upload.guschin.info" "http_file_share"
|
|
http_file_share_access = { "telegram.guschin.info", "guschin.info", "xmpp.guschin.info" }
|
|
ssl = {
|
|
key = "/etc/prosody/certs/guschin.info.key";
|
|
certificate = "/etc/prosody/certs/guschin.info.crt";
|
|
}
|
|
|
|
-- Telegram gateway (slidgram)
|
|
Component "telegram.guschin.info"
|
|
component_secret = os.getenv("SLIDGRAM_COMPONENT_SECRET")
|
|
ssl = {
|
|
key = "/etc/prosody/certs/guschin.info.key";
|
|
certificate = "/etc/prosody/certs/guschin.info.crt";
|
|
}
|