Prosody HTTP server
Prosody contains a mini built-in HTTP server, which is used for BOSH and other modules.
The following HTTP modules are supplied with Prosody:
- mod_bosh
- mod_websocket (in 0.10+)
- mod_http_files
- mod_http_file_share (in 0.12+)
mod_http will generally also be auto-loaded by most HTTP modules even if it isn’t specified in the config file. To explicitly enable HTTP, simply load mod_http by adding it to your config:
= {
modules_enabled ...
"http";
...
}
Port configuration
mod_http adds two services, ‘http’ and ‘https’. HTTP plugins are accessible via both services.
They use the standard port configuration. The defaults since 0.12.0 are:
= { 5280 }
http_ports = { "127.0.0.1", "::1" }
http_interfaces
= { 5281 }
https_ports = { "*", "::" } https_interfaces
So by default, https://yourprosody.example:5281/
will be
the base URLs used by HTTP plugins.
HTTPS Certificate
Prosody 0.12.x and later will automatically find and serve an appropriate certificate for HTTPS, based on the certificates already used for your XMPP services and the hostname requested by the client or web browser. No additional configuration should be necessary for most deployments.
In Prosody 0.11.x and earlier versions, only a single certificate is supported for HTTPS, and manual configuration is generally necessary. If you need support for multiple HTTPS domains, you should either include all the domains in the same certificate, or use a reverse proxy such as nginx in front of Prosody to handle your HTTPS. Reverse proxying is discussed later on this page.
Without a certificate configured, you will see an error like this:
Error binding encrypted port for https: No certificate present in SSL/TLS configuration for https port 5281
To fix it, specify a https_ssl
option in the global section to specify a
certificate manually. In Prosody 0.10 or later you can also use the
automatic location method by specifying a path or creating a
symlink.
Manual certificate configuration
If automatic location fails to find a suitable certificate, HTTPS
uses the global certificate used in the config file by default. If you
wish to use a different certificate, or change options, you can specify
this with https_ssl
in the global section
of your config file:
= {
https_ssl = "/path/to/http.crt";
certificate = "/path/to/http.key";
key }
Using this method effectively disables SNI support - in other words, only one certificate can be specified. If you need to serve multiple HTTPS hosts with different certificates, you will need to set up a suitable reverse proxy in front of Prosody (e.g. nginx, apache, haproxy or one of the many alternatives).
Automatic selection
In Prosody 0.10 the HTTPS service supports automatic certificate
detection via service
certificates, as well as the https_certificate
option.
= "certs/example.net.crt"
https_certificate -- key expected to be found in certs/example.net.key
Virtual hosts
Hosts defined in your config file automatically double as HTTP hosts when mod_http is loaded onto them (if you add mod_http to your global modules_enabled, it will automatically be loaded on every VirtualHost).
To handle HTTP requests to hosts that are not in your Prosody config, you have some options:
Setting a HTTP Host
To map a HTTP Host name to a specific VirtualHost:
"example.com"
VirtualHost = "www.example.com" http_host
http_host
declares the HTTP Host
header
that Prosody will map to a particular XMPP host as defined by
VirtualHost
or Component
. This should match
what either a browser or reverse proxy uses when it talks to directly to
Prosody’s built-in HTTP server.
⚠️ Note that if you may experience
unexpected behaviour if multiple VirtualHost
entries have
the same http_host
. See e.g. #1192.
Setting a default host
In the global section of your config, specify:
= "example.com" http_default_host
Any request for an unknown virtual host will be forwarded to the HTTP
modules on example.com
. If the intended VirtualHost has
http_host
set, then http_default_host
must be
set to the same value.
Path variables
Paths also support a $host
variable, allowing modules on
multiple virtual hosts to share a single public hostname.
= {
http_paths = "/register-on-$host";
register_web }
= "www.example.net"
http_host
"example.net" -- http://www.example.net/register-on-example.net
VirtualHost
"jabber.example" -- http://www.example.net/register-on-jabber.example VirtualHost
Path configuration
It’s possible to change the path that a module is reached at from its default. This is done via the http_paths config option, which may be set globally or per-host:
= {
http_paths = "/http-bind"; -- Serve BOSH at /http-bind
bosh files = "/"; -- Serve files from the base URL
}
The keys in the http_paths
config option mirror the
module names. For HTTP modules http_
is stripped.
Cross-domain (CORS) support
From version 0.12, Prosody’s HTTP server will automatically add CORS headers to allow web browsers to access Prosody’s URLs from other domains. For versions prior to 0.12, see individual module documentation for details about their CORS configuration.
Without CORS, web browsers apply a default “same-origin policy” which restricts access from other domains (including subdomains). While this security measure is generally necessary for many standard web apps, it is unnecessary for services that Prosody typically exposes, such as BOSH, websockets and file upload/download. That’s because these services have their own authentication mechanisms (not using cookies) or are designed for open access.
Prosody 0.12 supports the following CORS options in the global section of the config:
Option | Default | Notes |
---|---|---|
access_control_allow_methods | { "GET", "OPTIONS" } |
Allowed HTTP methods |
access_control_allow_headers | { "Content-Type" } |
Allowed HTTP headers |
access_control_allow_credentials | false |
Whether credentials should be allowed |
access_control_allow_origins | { "*" } |
List of origins that should be allowed |
access_control_max_age | 7200 (2 hours) |
Number of seconds a browser may cache the CORS settings for |
From Prosody 0.12.1, it is possible to override each module’s default
CORS settings via the http_cors_override
option in the
global section of your config.
For example, to disable CORS for mod_bosh and mod_websocket, you could set the following:
= {
http_cors_override = {
bosh = false;
enabled };
= {
websocket = false;
enabled };
}
As well as enabled
, you can also set
credentials
to true/false to indicate whether the
Access-Control-Allow-Credentials
header should be sent, and
you can override allowed headers
, methods
and
origins
on a per-app basis this way too.
Running behind a reverse proxy
External URL
Some modules expose their own URL in various ways. This URL is built
from the protocol, http_host
option and port used. If
Prosody sits behind a reverse proxy then this URL won’t be the public
one.
You can tell prosody about this by setting the
http_external_url
option, like this:
= "https://www.example.com/" http_external_url
Trusted reverse proxies
When a reverse proxy is used Prosody will not see the client’s IP,
only the proxy’s IP. Reverse proxies usually have ways to forward the
real client IP, commonly via a X-Forwarded-For
HTTP header.
Prosody understands this header but needs to know the IP of the proxy,
which is done via the trusted_proxies
setting:
= { "127.0.0.1", "::1", "192.168.1.1", } trusted_proxies
Starting with 0.12.0, Prosody also
supports CIDR notation (e.g. 192.168.1.0/24
),
allowing proxies within a specific IP range to be trusted. It also
supports the X-Forwarded-Proto
header, and will consider
the request secure if it has the value https
and comes from
a trusted proxy. This removes the need for
consider_bosh_secure
and similar settings.
Incorrect configuration of the trusted_proxies
setting,
or the proxy itself, may lead to security issues - e.g. allowing clients
to spoof their IP address and bypass rate limits or IP-based access
controls.
Example web server configuration
These examples show how to forward a whole domain to Prosody. It’s generally possible to forward only individual services by adjusting the path, see examples for BOSH and WebSockets.
Nginx
location / {
proxy_pass http://localhost:5280;
proxy_set_header Host "example.com";
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_buffering off;
tcp_nodelay on;
}
Lighttpd
For Lighttpd, proxy configuration looks something like this:
server.modules += ( "mod_proxy" )
proxy.server = (
"/http-bind" => (
( "host" => "127.0.0.1", "port" => 5280 )
)
)
Apache2 full example
See mod_proxy. Firstly, ensure you have the correct modules enabled in Apache:
a2enmod proxy proxy_http headers
To clarify the http settings, this example assumes you want to proxy your mod_http_file_share compoment as a whole and proxy only the bosh and websocket paths from your VirrtualHost. Your prosody VirutalHost is named “example.com”, the upload compoment is named “share.example.com” and your Website is “www.example.com”. You did not change the default http port. Then in the Apache config file for your domain, add the following lines:
<VirtualHost *:443>
ServerName www.example.com
SSLEngine On
SSLCertificateFile /path/to/certificatefolder/fullchain.pem
SSLCertificateKeyFile /path/to/certificatefolder/privkey.pem
# set RequestHeader to your prosody http_host.
# Its necessary if it is different from the ServerName like in this example:
RequestHeader set Host "example.com"
RequestHeader set X-Forwarded-Proto: https
ProxyPreserveHost On
ProxyPass / "http://127.0.0.1:5280/xmpp-websocket" upgrade=websocket timeout=900
ProxyPass / "http://127.0.0.1:5280/http-bind" #for bosh
ProxyPassReverse / "http://127.0.0.1:5280/http-bind"
</VirtualHost>
<VirtualHost *:443>
ServerName share.example.com
SSLEngine On
SSLCertificateFile /path/to/certificatefolder/fullchain.pem
SSLCertificateKeyFile /path/to/certificatefolder/privkey.pem
ProxyPreserveHost On
RequestHeader set X-Forwarded-Proto: https
#here the RequestHederHost is already the same as the Component name.
ProxyPreserveHost On
ProxyPass / "http://127.0.0.1:5280/"
ProxyPassReverse / "http://127.0.0.1:5280/"
</VirtualHost>
In the prosody.cfg.lua you would have globally loaded mod_websocket and mod_bosh. Your settings after the global section could look like this:
"example.com"
VirtualHost -- ... optional unrelated settings ...
"share.example.com" "http_file_share"
Component -- its not nessesary to have s2s loaded here:
= { "s2s" }
modules_disabled -- Change the Limit to 100MB:
= 1024 * 1024 * 100
http_file_share_size_limit = "2 weeks"
http_file_share_expires_after -- Set it to the same as the apache host above:
= "https://share.example.com/"
http_external_url -- here you see how we can manipulate the path:
= {
http_paths = "/"; --Serve from the base URL
file_share }
Adding HTTP-only hosts
You can also make a HTTP-only host via a dummy component:
"www.example.com" "http"
Component = { "bosh" } modules_enabled
HTTP modules such as mod_bosh must be loaded explicitly here as global modules are not loaded onto components by default.