Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

get_auto_url doesn't work with unix sockets #4345

Open
andreymal opened this issue Jan 25, 2025 · 10 comments
Open

get_auto_url doesn't work with unix sockets #4345

andreymal opened this issue Jan 25, 2025 · 10 comments

Comments

@andreymal
Copy link

andreymal commented Jan 25, 2025

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:

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"
@badlop
Copy link
Member

badlop commented Jan 27, 2025

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?

@andreymal
Copy link
Author

andreymal commented Jan 27, 2025

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 77163c4 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

@badlop
Copy link
Member

badlop commented Jan 27, 2025

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: a02cff0

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@ is andreymal.org but I've published ejabberd http at xmpp.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"

@andreymal
Copy link
Author

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

@zhidobandera
Copy link

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.

@andreymal
Copy link
Author

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)

@zhidobandera
Copy link

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)

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.

@zhidobandera
Copy link

(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)

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 :)

@zhidobandera
Copy link

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

@zhidobandera
Copy link

So, dear developers, will there be any investigation, clarifying questions, etc.?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants