Prosody: Difference between revisions
first version with link to manual |
add detailed config |
||
Line 2: | Line 2: | ||
It is documented in the [https://nixos.org/manual/nixos/stable/#module-services-prosody NixOS manual]. | It is documented in the [https://nixos.org/manual/nixos/stable/#module-services-prosody NixOS manual]. | ||
This page describes how to setup a walled-off Prosody instance for your organisation or family, with STUN/TURN support and http upload. This setup has server-to-server communication disabled. | |||
= SSL Certificate with ACME = | |||
This article assumes a working [[ACME]] configuration for certificate | |||
renewal. | |||
<syntaxhighlight lang="nix"> | |||
{ | |||
config, | |||
... | |||
}: | |||
let | |||
sslCertDir = config.security.acme.certs."example.org".directory; | |||
domainName = "example.org"; | |||
in | |||
{ | |||
# further prosody & coturn configuration goes here | |||
... | |||
} | |||
</syntaxhighlight> | |||
= Set up Prosody = | |||
== Open firewall for client to server c2s == | |||
<syntaxhighlight lang="nix"> | |||
networking.firewall = { | |||
allowedTCPPorts = [ | |||
# prosody client to server | |||
5222 | |||
5223 | |||
]; | |||
}; | |||
</syntaxhighlight> | |||
== Authentication and XMPP modules == | |||
<syntaxhighlight lang="nix"> | |||
services.prosody = { | |||
# this is a minimal server config with turn and http upload | |||
# all server to server connection are blocked | |||
enable = true; | |||
admins = [ "admin@${domainName}" ]; | |||
allowRegistration = false; | |||
authentication = "internal_plain"; | |||
s2sSecureAuth = true; | |||
c2sRequireEncryption = true; | |||
modules = { | |||
admin_adhoc = false; | |||
cloud_notify = false; | |||
pep = false; | |||
blocklist = false; | |||
bookmarks = false; | |||
dialback = false; | |||
ping = false; | |||
private = false; | |||
register = false; | |||
vcard_legacy = false; | |||
}; | |||
xmppComplianceSuite = false; | |||
}; | |||
</syntaxhighlight> | |||
== Setup Multi User Conference module == | |||
<syntaxhighlight lang="nix"> | |||
services.prosody = { | |||
muc = [ | |||
{ | |||
domain = "muc.xmpp.${domainName}"; | |||
# only admin can create public channels | |||
# everyone can create private chat rooms | |||
restrictRoomCreation = true; | |||
} | |||
]; | |||
} | |||
</syntaxhighlight> | |||
== Setup virtual host and ssl == | |||
<syntaxhighlight lang="nix"> | |||
services.prosody = { | |||
ssl = { | |||
cert = "${sslCertDir}/fullchain.pem"; | |||
key = "${sslCertDir}/key.pem"; | |||
}; | |||
virtualHosts = { | |||
# xmpp server for "@example.org" is hosted on "xmpp.example.org" | |||
# use SRV records. | |||
"xmpp.${domainName}" = { | |||
domain = "${domainName}"; | |||
enabled = true; | |||
}; | |||
}; | |||
}; | |||
</syntaxhighlight> | |||
You also need to set proper file permissions on the cert directory and key files. | |||
See [[ACME#Integration_with_service_modules]]. | |||
== Optional: use sqlite == | |||
<syntaxhighlight lang="nix"> | |||
services.prosody = { | |||
extraConfig = '' | |||
storage = "sql" | |||
sql = { | |||
driver = "SQLite3"; | |||
database = "prosody.sqlite"; -- The database name to use. For SQLite3 this the database filename (relative to the data storage directory). | |||
} | |||
''; | |||
}; | |||
</syntaxhighlight> | |||
sqlite seems to be more performant than the default file-backed | |||
storage driver. | |||
= Set up coturn = | |||
== Open firewall ports == | |||
<syntaxhighlight lang="nix"> | |||
networking.firewall = { | |||
allowedTCPPorts = [ | |||
# prosody turn/stun with coturn | |||
# see /run/coturn/turnserver.cfg | |||
3478 | |||
3479 | |||
5349 | |||
5350 | |||
]; | |||
allowedUDPPorts = [ | |||
# prosody turn/stun with coturn | |||
3478 | |||
3479 | |||
5349 | |||
5350 | |||
]; | |||
allowedUDPPortRanges = [ | |||
# coturn | |||
{ | |||
from = 49152; | |||
to = 65535; | |||
} | |||
]; | |||
}; | |||
</syntaxhighlight> | |||
== Set up coturn == | |||
<syntaxhighlight lang="nix"> | |||
age.secrets.prosody-coturn = { | |||
file = ./prosody-coturn.age; | |||
# -rw-r--r-- | |||
mode = "644"; | |||
}; | |||
services.coturn = { | |||
# https://prosody.im/doc/coturn | |||
enable = true; | |||
listening-port = 3478; | |||
pkey = "${sslCertDir}/key.pem"; | |||
cert = "${sslCertDir}/fullchain.pem"; | |||
realm = "turn.xmpp.${domainName}"; | |||
static-auth-secret-file = config.age.secrets.prosody-coturn.path; | |||
use-auth-secret = true; | |||
}; | |||
</syntaxhighlight> | |||
== Connect to prosody == | |||
<syntaxhighlight lang="nix"> | |||
services.prosody.virtualHosts."xmpp.${domainName}".extraConfig = '' | |||
turn_external_host = "turn.xmpp.${domainName}" | |||
turn_external_secret = "unfortunately this is a inline password" | |||
''; | |||
services.prosody.extraModules = [ "turn_external" ]; | |||
</syntaxhighlight> | |||
= http upload with prosody-filer and nginx = | |||
== Open firewall ports == | |||
<syntaxhighlight lang="nix"> | |||
networking.firewall = { | |||
allowedTCPPorts = [ | |||
# prosody https upload | |||
443 | |||
]; | |||
}; | |||
</syntaxhighlight> | |||
== Setup prosody-filer service == | |||
<syntaxhighlight lang="nix"> | |||
# set up directory for storing uploaded file | |||
systemd.services.prosody-filer.serviceConfig = { | |||
StateDirectory = "prosody-filer"; | |||
RuntimeDirectory = "prosody-filer"; | |||
RuntimeDirectoryMode = "0750"; | |||
}; | |||
services.prosody-filer = { | |||
enable = true; | |||
settings = { | |||
secret = "plain in line password"; | |||
storeDir = "/var/lib/prosody-filer/uploads/"; | |||
# this option refers to the upload url | |||
# https://upload.xmpp.${domainName}/upload/ | |||
# <-------> | |||
# do not change this, else 404 | |||
uploadSubDir = "upload/"; | |||
}; | |||
}; | |||
</syntaxhighlight> | |||
== Set up nginx virtual host == | |||
<syntaxhighlight lang="nix"> | |||
services.nginx = { | |||
clientMaxBodySize = "50m"; | |||
virtualHosts."upload.xmpp.${domainName}" = { | |||
forceSSL = true; | |||
useACMEHost = "${domainName}"; | |||
locations."/upload/" = { | |||
proxyPass = "http://localhost:5050/upload/"; | |||
# config copied from https://github.com/ThomasLeister/prosody-filer/blob/develop/README.md | |||
extraConfig = '' | |||
proxy_request_buffering off; | |||
if ( $request_method = OPTIONS ) { | |||
add_header Access-Control-Allow-Origin '*'; | |||
add_header Access-Control-Allow-Methods 'PUT, GET, OPTIONS, HEAD'; | |||
add_header Access-Control-Allow-Headers 'Authorization, Content-Type'; | |||
add_header Access-Control-Allow-Credentials 'true'; | |||
add_header Content-Length 0; | |||
add_header Content-Type text/plain; | |||
return 200; | |||
} | |||
''; | |||
}; | |||
}; | |||
}; | |||
</syntaxhighlight> | |||
== Connect filer to Prosody == | |||
<syntaxhighlight lang="nix"> | |||
services.prosody.extraConfig = '' | |||
Component "upload.xmpp.${domainName}" "http_upload_external" | |||
http_upload_external_secret = "should be the same pwd as above"; | |||
http_upload_external_base_url = "https://upload.xmpp.${domainName}/upload/" | |||
http_upload_external_file_size_limit = 52428800 | |||
''; | |||
services.prosody.virtualHosts."xmpp.${domainName}".extraConfig = '' | |||
disco_items = { | |||
{ "upload.${domainName}", "http upload" }; | |||
} | |||
''; | |||
# mod_http_upload_external is a community module | |||
# has to be installed via | |||
# https://modules.prosody.im/mod_http_upload_external.html#installation | |||
## Clone Prosody Community Modules Repo | |||
# cd /var/lib/prosody | |||
# hg clone https://hg.prosody.im/prosody-modules/ prosody-modules | |||
# update plugins via hg pull --update | |||
services.prosody.extraPluginPaths = [ | |||
"/var/lib/prosody/prosody-modules/mod_http_upload_external" | |||
]; | |||
</syntaxhighlight> | |||
[[Category:Server]] | [[Category:Server]] | ||
[[Category:NixOS Manual]] | [[Category:NixOS Manual]] |