get_auto_url doesn't work with unix sockets
Not sure if this is a bug report or a feature request, but after upgrading to Ubuntu 24.04 and ejabberd 23.10 I tried to use a unix socket with ejabberd_http because it is behind nginx and there is no point in using TCP:
listen:
-
port: "unix://run/ejabberd/ejabberd_http.socket"
unix_socket:
mode: "0660"
module: ejabberd_http
tls: false # handled by nginx
request_handlers:
/bosh: mod_bosh
/captcha: ejabberd_captcha
/upload: mod_http_upload
/ws: ejabberd_http_ws
/admin: ejabberd_web_admin
Unfortunately, this doesn't work:
[error] CRASH REPORT:
crasher:
ejabberd_captcha:init/1
<0.392.0>
[]
bad argument
in function integer_to_binary/1
called as integer_to_binary(<<"unix://run/ejabberd/ejabberd_http.socket">>)
not an integer
in call from ejabberd_captcha:get_auto_url/3 (ejabberd_captcha.erl, line 515)
in call from ejabberd_captcha:maybe_warning_norequesthandler/0 (ejabberd_captcha.erl, line 456)
in call from ejabberd_captcha:get_prog_name/0 (ejabberd_captcha.erl, line 450)
in call from ejabberd_captcha:is_feature_available/0 (ejabberd_captcha.erl, line 617)
in call from ejabberd_captcha:check_captcha_setup/0 (ejabberd_captcha.erl, line 624)
in call from ejabberd_captcha:init/1 (ejabberd_captcha.erl, line 294)
in call from gen_server:init_it/2 (gen_server.erl, line 851)
I see two get_auto_url functions in the ejabberd code, both require Port to be an integer:
- https://github.com/processone/ejabberd/blob/a19ab9f4e3586d6298f739b88b9e624bc282f815/src/ejabberd_captcha.erl#L516
- https://github.com/processone/ejabberd/blob/a19ab9f4e3586d6298f739b88b9e624bc282f815/src/mod_host_meta.erl#L161
Is it technically possible to refactor get_auto_url so that I manually set the base url so that it no longer tries to interpret Port as an integer?
I already did this for captcha and http upload, but it would be nice to configure the whole ejabberd_http module.
modules:
mod_http_upload:
put_url: "https://xmpp.andreymal.org/upload"
get_url: "https://xmpp.andreymal.org/files"
captcha_url: "https://xmpp.andreymal.org/captcha"
port: "unix://run/ejabberd/ejabberd_http.socket"
The syntax is unix: + path, for example: port: "unix:/run/ejabberd/ejabberd_http.socket"
register: false
What is that? Where did you get the idea to add it?
[error] CRASH REPORT:
Oops, it should handle that case and give a nice error message, instead of crashing like that. This can be considered a bug in ejabberd.
Is it technically possible to refactor get_auto_url so that I manually set the base url
Notice that get_url and put_url options in mod_http_upload support @HOST@, so you can configure something like this:
put_url: "https://@HOST@:5443/upload"
Maybe captcha_url should support @HOST@ too?
The syntax is
unix:+ path, for example:port: "unix:/run/ejabberd/ejabberd_http.socket"
If you're complaining about that double slash, I copied it from the official example https://web.archive.org/web/20250114033310/https://www.process-one.net/blog/ejabberd-23-10/#new-unixsocket-listener-option
What is that? Where did you get the idea to add it?
From the official example https://github.com/processone/ejabberd/blob/18.06/ejabberd.yml.example#L192
(I see this was removed in https://github.com/processone/ejabberd/commit/77163c43d243daadcc351a8b26ed3b285d379d80 but I created my ejabberd configuration in 2015 so it's been here all these 10 years 🙃)
@HOST@
Not in my case, @HOST@ is andreymal.org but I've published ejabberd http at xmpp.andreymal.org
I copied it from the official example https://www.process-one.net/blog/ejabberd-23-10/#new-unixsocket-listener-option
Aha, thanks! I've fixed that example to match the syntax described in the documentation.
From the official example https://github.com/processone/ejabberd/blob/18.06/ejabberd.yml.example#L192
Wow, I completely forgot that was supported in the past, and it's surprising that it's still supported.
I see it emits a warning since several years ago: https://github.com/processone/ejabberd/commit/a02cff0e780bb735531594c4ece81e8628f79782
2025-01-27 13:13:08.050728+01:00 [warning]
Listening option 'register' is deprecated and was automatically
replaced by HTTP request handler: "/register" -> mod_register_web.
Please adjust your configuration file accordingly.
Hint: run `ejabberdctl dump-config` command to view
current configuration as it is seen by ejabberd.
Using deprecated options in a recent version reduces legibility of the configuration file, can you follow this and any other recommendations mentioned in the logs? At least if you share that configuration with other people and expect them to read it.
@HOST@isandreymal.orgbut I've published ejabberd http atxmpp.andreymal.org
Ohh, ok. In that case it's impossible for auto to determine correctly the URL. For such scenarios, the solution is to set the URL manually, as you did.
If I understand correctly, you are thinking in some way of semi-automated option, right? That would be a new feature... let's imagine how it could be used, and later see what implementation work would require and if it's worth.
For example, that example configuration is not supported at all. If this were supported, would it be useful for your case?
hosts:
- andreymal.org
- example.org
define_macro:
HOST_NGINX: "xmpp.andreymal.org"
modules:
mod_http_upload:
put_url: "https://@HOST_NGINX@/upload"
get_url: "https://@HOST_NGINX@/files"
captcha_url: "https://@HOST_NGINX@/captcha"
My primary goal is to get the unix socket working, setting the base url is more of a “nice to have” to reduce duplication in the config, but this is not really important to me
In fact, my ejabberd configuration is generated by Ansible, and the source looks like captcha_url: "https://{{ ejabberd_http_host }}/captcha" where ejabberd_http_host is an Ansible variable, so I personally don't really need to use a macro ¯\_(ツ)_/¯
But I think your idea might be useful for other users who don't use Ansible
At least if you share that configuration with other people and expect them to read it.
Good point, I removed register: from the issue text so as not to confuse other users
I'm not sure if I should create a separate issue, but it seems like the unix socket isn't working at all. For example, I tried to set up a jabber server in the onion network with the following configuration:
$ cat /etc/tor/torrc
User tor
DataDirectory /var/lib/tor
HiddenServiceDir /var/lib/tor/hidden_service/
HiddenServicePort 5222 unix:/tmp/c2s.sock
HiddenServicePort 5269 unix:/tmp/s2s.sock
$ cat /etc/ejabberd/ejabberd.yml
hosts:
- "abc.onion"
listen:
-
port: "unix:/tmp/c2s.sock"
module: ejabberd_c2s
max_stanza_size: 262144
shaper: c2s_shaper
access: c2s
starttls_required: false
-
port: "unix:/tmp/s2s.sock"
module: ejabberd_s2s_in
max_stanza_size: 524288
shaper: s2s_shaper
The jabber client is configured to use the tor proxy (of course), but the connection doesn't work, and there are no attempts in the logs. I tried experimenting with the unix_socket option (which, by the way, has no documentation, only a mention in the changelog, which is strange lol). These experiments didn't lead to any result.
Interesting, I see Start accepting TCP connections at unix:/run/ejabberd/s2s.socket for ejabberd_s2s_in in my log, but this file doesn't exist (but my version is 23.10, maybe this is fixed in newer versions, I haven't tested this yet)
(when using /tmp, note that the systemd option PrivateTmp=yes can create a separate mountpoint and you will never see files from ejabberd's /tmp, that's why I use /run instead)
Interesting, I see
Start accepting TCP connections at unix:/run/ejabberd/s2s.socket for ejabberd_s2s_inin my log, but this file doesn't exist (but my version is 23.10, maybe this is fixed in newer versions, I haven't tested this yet)
Yeah, I also noticed that the file is not created if a path other than /var/lib/ejabberd/socket/ is specified. If I specify it directly as port: "unix:/var/lib/ejabberd/socket/abc.sock", then the "abc.sock" file is created, but still nothing works. And no, nothing has been fixed in the newer versions. I'm using Arch Linux for this set up, so I have the latest version.
(when using
/tmp, note that the systemd optionPrivateTmp=yescan create a separate mountpoint and you will never see files from ejabberd's/tmp, that's why I use/runinstead)
I’ve gone really deep into this... problem, played around with the systemd service file, changed the caps - nothing helps. Honestly, I’m starting to get pretty frustrated with this :)
Here is a 99% default service file that comes with the package in Arch Linux. The only change I made in this case is removing AmbientCapabilities=CAP_NET_BIND_SERVICE, as it is simply not needed in the context of unix socket.
$ cat /lib/systemd/system/ejabberd.service
[Unit]
Description=XMPP Server
After=network.target
[Service]
Type=notify
User=jabber
Group=jabber
LimitNOFILE=65536
Restart=on-failure
RestartSec=5
ExecStart=/usr/bin/ejabberdctl foreground
ExecStop=/bin/sh -c '/usr/bin/ejabberdctl stop && /usr/bin/ejabberdctl stopped'
ExecReload=/usr/bin/ejabberdctl reload_config
NotifyAccess=all
PrivateDevices=true
TimeoutSec=300
[Install]
WantedBy=multi-user.target
So, dear developers, will there be any investigation, clarifying questions, etc.?
The accumulated problem description in this issue involves ejabberd 23.10, recent ejabberd, nginx, tor, systemd and all their configuration files. That is spread in several consecutive comments that add a few more information.
Maybe, if there's a clear list of steps to reproduce the problem, that include only the barely minimum to provoke the problem, and one problem is addressed at a time... that would lower the barrier to enter this issue. And I wonder if that would help people look into it.
At least my report doesn't require nginx/tor/systemd
The accumulated problem description in this issue involves ejabberd 23.10, recent ejabberd, nginx, tor, systemd and all their configuration files. That is spread in several consecutive comments that add a few more information.
Maybe, if there's a clear list of steps to reproduce the problem, that include only the barely minimum to provoke the problem, and one problem is addressed at a time... that would lower the barrier to enter this issue. And I wonder if that would help people look into it.
The point is different - does anyone have a working example of using a unix socket, regardless of the context, whether it's tor, nginx, or any other software working in conjunction with ejabberd?
To reproduce the issue, I provided an example - all that needs to be done is to create a hidden service and specify the unix socket (created by ejabberd) in the Tor configuration file (torrc).
As for systemd, it's merely speculation that it could be the cause of the issue, but, in my opinion, that's not the case.
The point is different - does anyone have a working example of using a unix socket, regardless of the context, whether it's tor, nginx, or any other software working in conjunction with ejabberd?
Yes, there is a working example, fully published and 100% reproducible: this PR uses unix domain socket and curl.
Yes, there is a working example, fully published and 100% reproducible: this PR uses unix domain socket and curl.
I mean for s2s and c2s
I see it emits a warning since several years ago:
By the way, it emits a warning only if register is true, but since I used register: false instead, I didn't have any warnings in the logs
it emits a warning only if register is true
Wow, right! That explains why you didn't update old configuration.
I've fixed that, now it shows a warning whenever those options are used. Thanks!