Ejabberd is a very flexible and scalable XMPP server. We use it because it can be configured using a simple yaml configuration file and managed via ejabberdctl commands. This makes it a good fit for our infrastructure as code approach. That said, ejabberd does require one to understand the XMPP protocol/jargon as it does not abstract away any of it. So simple things like creating chatrooms, limiting access to them and playing history backlog to users who connected them can be an effort if you've never done it.
Ejabberd is very modular. To get an idea check the Module options page. Almost everything is a module, including multi-user chatroom support, which handled by mod_muc. To configure room options with ejabberdctl (e.g. make a room "members_only") you also need mod_muc_admin.
Access to the multi-user chat feature can be limited to certain users using mod_muc's access options that utilize access rules. These access controls are global so if a user is not in the allow list he/she will not have any access to any chat rooms on the server.
Multi-user chat room have a set of room options. These are documented well in the mod_muc documentation under "default room options" which get inherited by every new room. Changes made to default room options will not propagate to existing rooms, though.
In our case we wanted to have one public room and one private "members only" room where users were explicitly "affiliated" with the room. With the default ejabberd settings creating a public room is quite trivial:
ejabberdctl create-room public conference.chat.example.org chat.example.org
To create a private (members only) room more work is needed. First get a list of users on your XMPP server (cluster):
ejabberdctl registered_users chat.example.org admin yoda luke.skywalker han.solo obiwan.kenobi
Create the room:
ejabberdctl create-room private conference.chat.example.org chat.example.org
Make the room members only:
ejabberdctl change_room_option private conference.chat.example.org members_only true
Add members to the room:
ejabberdctl set_room_affiliation private conference.chat.example.org email@example.com member ejabberdctl set_room_affiliation private conference.chat.example.org firstname.lastname@example.org member
Now poor Han Solo will not be able to join this "Jedi-only" room.
ejabberdctl get_room_affiliations private conference.chat.example.org luke.skywalker chat.example.org member obiwan.kenobi chat.example.org member yoda chat.example.org owner
The creator of the room, here "yoda", is allowed access automatically. It seems that ejabberdctl makes the local system user the room was created as the room owner.
At this point it makes sense to verify the room options:
ejabberdctl get_room_options private conference.chat.example.org
Cross-reference the options against mod_muc's default_room_options documentation to make sure everything is configured as you wish.
You may also want to make your rooms persistent, so that they don't get destroyed even if all members disconnect:
ejabberdctl change_room_option public conference.chat.example.org persistent true ejabberdctl change_room_option private conference.chat.example.org persistent true
For a full list of multi-user chat admin commands refer to muc_admin documentation.