<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>即时通信 on 勇气</title><link>https://courages.us/tag/%E5%8D%B3%E6%97%B6%E9%80%9A%E4%BF%A1/</link><description>Recent content in 即时通信 on 勇气</description><generator>Hugo -- gohugo.io</generator><language>zh-cn</language><lastBuildDate>Fri, 20 Nov 2020 11:32:28 +0800</lastBuildDate><atom:link href="https://courages.us/tag/%E5%8D%B3%E6%97%B6%E9%80%9A%E4%BF%A1/index.xml" rel="self" type="application/rss+xml"/><item><title>即时通信IRC服务Oragono</title><link>https://courages.us/%E5%8D%B3%E6%97%B6%E9%80%9A%E4%BF%A1irc%E6%9C%8D%E5%8A%A1oragono/</link><pubDate>Wed, 18 Nov 2020 15:19:05 +0800</pubDate><guid>https://courages.us/%E5%8D%B3%E6%97%B6%E9%80%9A%E4%BF%A1irc%E6%9C%8D%E5%8A%A1oragono/</guid><description>&lt;p&gt;前一篇讲了&lt;a class="link" href="https://courages.us/%e5%8d%b3%e6%97%b6%e9%80%9a%e4%bf%a1xmpp%e6%9c%8d%e5%8a%a1%e5%99%a8ejabberd-openfire/" target="_blank" rel="noopener"&#10; &gt;XMPP通信&lt;/a&gt;，还有一种比它还早的协议&lt;a class="link" href="https://zh.wikipedia.org/wiki/IRC" target="_blank" rel="noopener"&#10; &gt;IRC（Internet Relay Chat）&lt;/a&gt;，是一种简单的文本聊天协议，支持一对一聊天和群聊（频道）。通常IRC聊天只需要昵称而不需要密码（也可以使用密码），这与XMML不同，使得它可以作为公开的聊天频道，比如游戏直播平台Twitch就使用类似的功能来实现聊天。IRC同样有许多服务端，比如&lt;a class="link" href="https://www.inspircd.org/" target="_blank" rel="noopener"&#10; &gt;InspIRCd&lt;/a&gt;和客户端软件，比如&lt;a class="link" href="https://irssi.org/" target="_blank" rel="noopener"&#10; &gt;Irssi&lt;/a&gt;，也可以直接连接公开的IRC服务器，比如&lt;a class="link" href="https://freenode.net/" target="_blank" rel="noopener"&#10; &gt;Freenode&lt;/a&gt;。事实上IRC协议非常简单，只要能对相应的&lt;a class="link" href="https://ircv3.net/irc/" target="_blank" rel="noopener"&#10; &gt;命令&lt;/a&gt;作出响应就可以在各个客户端之间通信，因此有许多不同编程语言的服务端/客户端实现。&lt;a class="link" href="https://github.com/oragono/oragono" target="_blank" rel="noopener"&#10; &gt;Oragono&lt;/a&gt;便是IRC 服务器的Golang实现，支持&lt;a class="link" href="https://ircv3.net/" target="_blank" rel="noopener"&#10; &gt;IRCv3&lt;/a&gt;，支持SASL/LDAP认证，支持服务端保存消息历史记录。&lt;br&gt;&#10;Oragono运行很简单，克隆代码，编辑配置文件就可以了&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;➜  oragono24 ls&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;CHANGELOG.md     README           default.yaml     docs             languages        oragono          oragono.motd     traditional.yaml&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;➜  oragono24 cp default.yaml ircd.yaml&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;➜  oragono24 ./oragono mkcerts&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2020/11/11 12:01:04 making self-signed certificates&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2020/11/11 12:01:04  making cert &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; :6697 listener&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2020/11/11 12:01:04   Certificate created at fullchain.pem : privkey.pem&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;➜  oragono24 ls&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;CHANGELOG.md     README           default.yaml     docs             fullchain.pem    ircd.yaml        languages        oragono          oragono.motd     privkey.pem      traditional.yaml&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;➜  oragono24 ./oragono run&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2020-11-13T03:09:29.320Z : info : server : oragono-2.4.0 starting&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2020-11-13T03:09:29.320Z : info : server : Using config file : ircd.yaml&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2020-11-13T03:09:29.320Z : info : server : Using datastore : ircd.db&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2020-11-13T03:09:29.344Z : info : server : Proxied IPs will be accepted from : localhost&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2020-11-13T03:09:29.345Z : info : listeners : now listening on &lt;span style="color:#f92672"&gt;[&lt;/span&gt;::1&lt;span style="color:#f92672"&gt;]&lt;/span&gt;:6667, tls&lt;span style="color:#f92672"&gt;=&lt;/span&gt;false, tlsproxy&lt;span style="color:#f92672"&gt;=&lt;/span&gt;false, tor&lt;span style="color:#f92672"&gt;=&lt;/span&gt;false, websocket&lt;span style="color:#f92672"&gt;=&lt;/span&gt;false.&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2020-11-13T03:09:29.345Z : info : listeners : now listening on :6697, tls&lt;span style="color:#f92672"&gt;=&lt;/span&gt;true, tlsproxy&lt;span style="color:#f92672"&gt;=&lt;/span&gt;false, tor&lt;span style="color:#f92672"&gt;=&lt;/span&gt;false, websocket&lt;span style="color:#f92672"&gt;=&lt;/span&gt;false.&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2020-11-13T03:09:29.345Z : info : listeners : now listening on :8097, tls&lt;span style="color:#f92672"&gt;=&lt;/span&gt;true, tlsproxy&lt;span style="color:#f92672"&gt;=&lt;/span&gt;false, tor&lt;span style="color:#f92672"&gt;=&lt;/span&gt;false, websocket&lt;span style="color:#f92672"&gt;=&lt;/span&gt;true.&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2020-11-13T03:09:29.345Z : info : listeners : now listening on 127.0.0.1:6667, tls&lt;span style="color:#f92672"&gt;=&lt;/span&gt;false, tlsproxy&lt;span style="color:#f92672"&gt;=&lt;/span&gt;false, tor&lt;span style="color:#f92672"&gt;=&lt;/span&gt;false, websocket&lt;span style="color:#f92672"&gt;=&lt;/span&gt;false.&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2020-11-13T03:09:29.345Z : info : server : Server running&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2020-11-13T03:09:38.386Z : info : connect-ip : Client connecting: real IP 192.168.33.1, proxied IP &amp;lt;nil&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2020-11-13T03:09:38.439Z : info : accounts : client : * : logged into account : kiwi-n30&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2020-11-13T03:09:38.442Z : info : connect : Client connected &lt;span style="color:#f92672"&gt;[&lt;/span&gt;kiwi-n30&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;u:~u&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;r:https://kiwiirc.com/&lt;span style="color:#f92672"&gt;]&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2020-11-13T03:09:40.955Z : info : connect-ip : Client connecting: real IP 192.168.33.1, proxied IP &amp;lt;nil&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2020-11-13T03:09:40.963Z : info : connect : Client connected &lt;span style="color:#f92672"&gt;[&lt;/span&gt;kiwi-n28&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;u:~u&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;r:https://kiwiirc.com/&lt;span style="color:#f92672"&gt;]&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2020-11-13T03:09:56.198Z : info : connect-ip : Client connecting: real IP 192.168.33.1, proxied IP &amp;lt;nil&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2020-11-13T03:09:56.209Z : info : connect : Client connected &lt;span style="color:#f92672"&gt;[&lt;/span&gt;kiwi-n29&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;u:~u&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;r:https://kiwiirc.com/&lt;span style="color:#f92672"&gt;]&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;编辑ircd.yml，设置管理密码，启用一下WebSocket，保存历史消息到MySQL。opers/admin管理密码在认证管理员的时候使用的，可以使用命令oragono genpasswd生成。ircd.db用来保存注册用户，使用的并不是SQLite，而是Golang实现的一个嵌入式的内存Key/Value存储&lt;a class="link" href="https://github.com/tidwall/buntdb" target="_blank" rel="noopener"&#10; &gt;BuntDB&lt;/a&gt;，可以持久化到硬盘。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# network configuration&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;network&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# name of the network&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;name&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;OragonoTest&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# server configuration&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;server&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# server name&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;name&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;oragono.test&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# addresses to listen on&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;listeners&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# The standard plaintext port for IRC is 6667. Allowing plaintext over the&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# public Internet poses serious security and privacy issues. Accordingly,&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# we recommend using plaintext only on local (loopback) interfaces:&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;127.0.0.1:6667&amp;#34;: &lt;/span&gt;&lt;span style="color:#75715e"&gt;# (loopback ipv4, localhost-only)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;[::1]:6667&amp;#34;: &lt;/span&gt; &lt;span style="color:#75715e"&gt;# (loopback ipv6, localhost-only)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# If you need to serve plaintext on public interfaces, comment out the above&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# two lines and uncomment the line below (which listens on all interfaces):&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# &amp;#34;:6667&amp;#34;:&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# Alternately, if you have a TLS certificate issued by a recognized CA,&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# you can configure port 6667 as an STS-only listener that only serves&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# &amp;#34;redirects&amp;#34; to the TLS port, but doesn&amp;#39;t allow chat. See the manual&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# for details.&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# The standard SSL/TLS port for IRC is 6697. This will listen on all interfaces:&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;:6697&amp;#34;&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;tls&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;cert&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;fullchain.pem&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;key&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;privkey.pem&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# &amp;#39;proxy&amp;#39; should typically be false. It&amp;#39;s only for Kubernetes-style load&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# balancing that does not terminate TLS, but sends an initial PROXY line&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# in plaintext.&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;proxy&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;false&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# Example of a Unix domain socket for proxying:&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# &amp;#34;/tmp/oragono_sock&amp;#34;:&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# Example of a Tor listener: any connection that comes in on this listener will&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# be considered a Tor connection. It is strongly recommended that this listener&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# *not* be on a public interface --- it should be on 127.0.0.0/8 or unix domain:&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# &amp;#34;/hidden_service_sockets/oragono_tor_sock&amp;#34;:&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# tor: true&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# Example of a WebSocket listener:&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;:8097&amp;#34;&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;websocket&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;tls&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;cert&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;fullchain.pem&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;key&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;privkey.pem&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# ircd operators&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;opers&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# operator named &amp;#39;admin&amp;#39;; log in with /OPER admin [password]&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;admin&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# which capabilities this oper has access to&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;class&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;server-admin&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# custom whois line&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;whois-line&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;is a server admin&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# custom hostname&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;vhost&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;staff&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# normally, operator status is visible to unprivileged users in WHO and WHOIS&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# responses. this can be disabled with &amp;#39;hidden&amp;#39;. (&amp;#39;hidden&amp;#39; also causes the&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# &amp;#39;vhost&amp;#39; line above to be ignored.)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;hidden&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;false&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# modes are modes to auto-set upon opering-up. uncomment this to automatically&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# enable snomasks (&amp;#34;server notification masks&amp;#34; that alert you to server events;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# see `/quote help snomasks` while opered-up for more information):&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;#modes: +is acjknoqtuxv&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# operators can be authenticated either by password (with the /OPER command),&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# or by certificate fingerprint, or both. if a password hash is set, then a&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# password is required to oper up (e.g., /OPER dan mypassword). to generate&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# the hash, use `oragono genpasswd`.&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;password&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;$2a$04$I2Yhr7UF4p3iyEZcKTPJgukLA9mm00B1wQgicJvGZP/gf0u0tbQQy&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# datastore configuration&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;datastore&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# path to the datastore&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;path&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;ircd.db&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# if the database schema requires an upgrade, `autoupgrade` will attempt to&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# perform it automatically on startup. the database will be backed&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# up, and if the upgrade fails, the original database will be restored.&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;autoupgrade&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# connection information for MySQL (currently only used for persistent history):&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;mysql&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;enabled&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;host&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;127.0.0.1&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;port&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;3306&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# if socket-path is set, it will be used instead of host:port&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;#socket-path: &amp;#34;/var/run/mysqld/mysqld.sock&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;user&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;root&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;password&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;root&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;history-database&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;oragono_history&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;timeout&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;30s&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;IRC服务端设置好了，使用客户端连上去就可以聊天了。IRC协议类似HTTP协议，服务器地址类似irc://irc.freenode.net，但是也可以使用web来连接，前面配置了监听来自8097端口的websocket请求。这里使用web的IRC客户端&lt;a class="link" href="https://kiwiirc.com/" target="_blank" rel="noopener"&#10; &gt;Kiwi IRC&lt;/a&gt;，这是Vue实现的一个web客户端，各个组件之间通过触发/订阅Vue实例状态/事件变化进行通信，支持自定义组件/中间件，这也是Freenode使用的客户端。Kiwiirc主要聚焦连接和消息的处理，比如websocket连接/发送/监听，消息的格式化/通知/声音/状态。它能够连接websocket的IRC服务器，甚至还提供在线&lt;a class="link" href="https://kiwiirc.com/clientbuilder/#/" target="_blank" rel="noopener"&#10; &gt;生成器&lt;/a&gt;，只需要添加websocket url就好了&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;windowTitle&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;Kiwi IRC with Oragono Test&amp;#34;&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;startupScreen&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;welcome&amp;#34;&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;kiwiServer&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;http://oragono.test&amp;#34;&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;restricted&amp;#34;&lt;/span&gt;: false,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;theme&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;Default&amp;#34;&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;themes&amp;#34;&lt;/span&gt;: &lt;span style="color:#f92672"&gt;[&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;{&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;Default&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;url&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;static/themes/default&amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;}&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;{&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;Dark&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;url&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;static/themes/dark&amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;}&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;{&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;Coffee&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;url&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;static/themes/coffee&amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;}&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;{&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;GrayFox&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;url&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;static/themes/grayfox&amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;}&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;{&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;Nightswatch&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;url&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;static/themes/nightswatch&amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;}&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;{&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;Osprey&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;url&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;static/themes/osprey&amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;}&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;{&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;Radioactive&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;url&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;static/themes/radioactive&amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;}&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;{&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;Sky&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;url&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;static/themes/sky&amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;}&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;{&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;Elite&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;url&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;static/themes/elite&amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;]&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;startupOptions&amp;#34;&lt;/span&gt; : &lt;span style="color:#f92672"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;websocket&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;wss://127.0.0.1:8097&amp;#34;&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;channel&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;#kiwiirc-default&amp;#34;&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;nick&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;kiwi-n?&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;}&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;embedly&amp;#34;&lt;/span&gt;: &lt;span style="color:#f92672"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;key&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;}&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;plugins&amp;#34;&lt;/span&gt;: &lt;span style="color:#f92672"&gt;[&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;{&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;customise&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;url&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;static/plugins/customise.html&amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;]&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;运行登录后的效果&lt;br&gt;&#10;&lt;a class="link" href="https://courages.us/wp-content/uploads/2020/11/kiwi_action.png" target="_blank" rel="noopener"&#10; &gt;&lt;img class="gallery-image" data-flex-basis="310px" data-flex-grow="129" height="232" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://courages.us/wp-content/uploads/2020/11/kiwi_action-300x232.png" width="300"&gt;&lt;/a&gt;&lt;/p&gt;&#10;&lt;p&gt;&lt;a class="link" href="https://courages.us/wp-content/uploads/2020/11/kiwi_auth.png" target="_blank" rel="noopener"&#10; &gt;&lt;img class="gallery-image" data-flex-basis="566px" data-flex-grow="236" height="127" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://courages.us/wp-content/uploads/2020/11/kiwi_auth-300x127.png" width="300"&gt;&lt;/a&gt;&lt;/p&gt;&#10;&lt;p&gt;&lt;a class="link" href="https://courages.us/wp-content/uploads/2020/11/kiwi_auth_no.png" target="_blank" rel="noopener"&#10; &gt;&lt;img class="gallery-image" data-flex-basis="660px" data-flex-grow="275" height="109" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://courages.us/wp-content/uploads/2020/11/kiwi_auth_no-300x109.png" width="300"&gt;&lt;/a&gt;&lt;/p&gt;&#10;&lt;p&gt;&lt;a class="link" href="https://courages.us/wp-content/uploads/2020/11/kiwi_channel.png" target="_blank" rel="noopener"&#10; &gt;&lt;img class="gallery-image" data-flex-basis="960px" data-flex-grow="400" height="75" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://courages.us/wp-content/uploads/2020/11/kiwi_channel-300x75.png" width="300"&gt;&lt;/a&gt;&lt;/p&gt;&#10;&lt;p&gt;&lt;a class="link" href="https://courages.us/wp-content/uploads/2020/11/kiwi_channel_register.png" target="_blank" rel="noopener"&#10; &gt;&lt;img class="gallery-image" data-flex-basis="406px" data-flex-grow="169" height="177" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://courages.us/wp-content/uploads/2020/11/kiwi_channel_register-300x177.png" width="300"&gt;&lt;/a&gt;&lt;/p&gt;&#10;&lt;p&gt;&lt;a class="link" href="https://courages.us/wp-content/uploads/2020/11/kiwi_invite.png" target="_blank" rel="noopener"&#10; &gt;&lt;img class="gallery-image" data-flex-basis="293px" data-flex-grow="122" height="245" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://courages.us/wp-content/uploads/2020/11/kiwi_invite-300x245.png" width="300"&gt;&lt;/a&gt;&lt;/p&gt;&#10;&lt;p&gt;&lt;a class="link" href="https://courages.us/wp-content/uploads/2020/11/kiwi_join_history.png" target="_blank" rel="noopener"&#10; &gt;&lt;img class="gallery-image" data-flex-basis="431px" data-flex-grow="179" height="167" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://courages.us/wp-content/uploads/2020/11/kiwi_join_history-300x167.png" width="300"&gt;&lt;/a&gt;&lt;/p&gt;&#10;&lt;p&gt;&lt;a class="link" href="https://courages.us/wp-content/uploads/2020/11/kiwi_join_self.png" target="_blank" rel="noopener"&#10; &gt;&lt;img class="gallery-image" data-flex-basis="452px" data-flex-grow="188" height="159" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://courages.us/wp-content/uploads/2020/11/kiwi_join_self-300x159.png" width="300"&gt;&lt;/a&gt;&lt;/p&gt;&#10;&lt;p&gt;&lt;a class="link" href="https://courages.us/wp-content/uploads/2020/11/kiwi_login.png" target="_blank" rel="noopener"&#10; &gt;&lt;img class="gallery-image" data-flex-basis="566px" data-flex-grow="236" height="127" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://courages.us/wp-content/uploads/2020/11/kiwi_login-300x127.png" width="300"&gt;&lt;/a&gt;&lt;/p&gt;&#10;&lt;p&gt;&lt;a class="link" href="https://courages.us/wp-content/uploads/2020/11/kiwi_oper.png" target="_blank" rel="noopener"&#10; &gt;&lt;img class="gallery-image" data-flex-basis="231px" data-flex-grow="96" height="300" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://courages.us/wp-content/uploads/2020/11/kiwi_oper-289x300.png" width="289"&gt;&lt;/a&gt;&lt;/p&gt;&#10;&lt;p&gt;&lt;a class="link" href="https://courages.us/wp-content/uploads/2020/11/kiwi_preload.png" target="_blank" rel="noopener"&#10; &gt;&lt;img class="gallery-image" data-flex-basis="489px" data-flex-grow="204" height="147" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://courages.us/wp-content/uploads/2020/11/kiwi_preload-300x147.png" width="300"&gt;&lt;/a&gt;&lt;br&gt;&#10;其实IRC是基于TCP连接的文本交互的，也可以使用telnet来模拟&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;➜ ~ telnet 127.0.0.1 &lt;span style="color:#ae81ff"&gt;6667&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Trying 127.0.0.1...&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Connected to localhost.&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Escape character is &lt;span style="color:#e6db74"&gt;&amp;#39;^]&amp;#39;&lt;/span&gt;.&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;CAP LS &lt;span style="color:#ae81ff"&gt;302&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;:oragono.test CAP * LS * :account-notify account-tag away-notify batch cap-notify chghost draft/channel-rename draft/chathistory draft/event-playback draft/languages&lt;span style="color:#f92672"&gt;=&lt;/span&gt;16,en,~bs,~de,~el,~en-AU,~es,~fi,~fr-FR,~it,~nl,~no,~pl,~pt-BR,~ro,~tr-TR,~zh-CN draft/multiline&lt;span style="color:#f92672"&gt;=&lt;/span&gt;max-bytes&lt;span style="color:#f92672"&gt;=&lt;/span&gt;4096,max-lines&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;100&lt;/span&gt; draft/register&lt;span style="color:#f92672"&gt;=&lt;/span&gt;before-connect draft/relaymsg&lt;span style="color:#f92672"&gt;=&lt;/span&gt;/ draft/resume-0.5 echo-message extended-join invite-notify labeled-response message-tags multi-prefix oragono.io/nope sasl&lt;span style="color:#f92672"&gt;=&lt;/span&gt;PLAIN,EXTERNAL server-time setname&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;:oragono.test CAP * LS :userhost-in-names znc.in/playback znc.in/self-message&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;NICK kiwi-n26&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;USER kiwi-n26 &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; * https://kiwiirc.com/&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;CAP REQ :account-notify account-tag away-notify batch cap-notify draft/chathistory extended-join invite-notify message-tags multi-prefix server-time userhost-in-names znc.in/self-message&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:02.201Z :oragono.test CAP * ACK :account-notify account-tag away-notify batch cap-notify draft/chathistory extended-join invite-notify message-tags multi-prefix server-time userhost-in-names znc.in/self-message&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;CAP END&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;001&lt;/span&gt; kiwi-n26 :Welcome to the Internet Relay Network kiwi-n26&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;002&lt;/span&gt; kiwi-n26 :Your host is oragono.test, running version oragono-2.4.0&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;003&lt;/span&gt; kiwi-n26 :This server was created Fri, &lt;span style="color:#ae81ff"&gt;13&lt;/span&gt; Nov &lt;span style="color:#ae81ff"&gt;2020&lt;/span&gt; 00:35:48 UTC&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;004&lt;/span&gt; kiwi-n26 oragono.test oragono-2.4.0 BERTZios CEIMRUabehiklmnoqstuv Iabehkloqv&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;005&lt;/span&gt; kiwi-n26 AWAYLEN&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;390&lt;/span&gt; BOT&lt;span style="color:#f92672"&gt;=&lt;/span&gt;B CASEMAPPING&lt;span style="color:#f92672"&gt;=&lt;/span&gt;ascii CHANLIMIT&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#75715e"&gt;#:100 CHANMODES=Ibe,k,l,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m INVEX KICKLEN=390 MAXLIST=beI:60 :are supported by this server&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;005&lt;/span&gt; kiwi-n26 MAXTARGETS&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;4&lt;/span&gt; MODES MONITOR&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;100&lt;/span&gt; NETWORK&lt;span style="color:#f92672"&gt;=&lt;/span&gt;OragonoTest NICKLEN&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;32&lt;/span&gt; PREFIX&lt;span style="color:#f92672"&gt;=(&lt;/span&gt;qaohv&lt;span style="color:#f92672"&gt;)&lt;/span&gt;~&amp;amp;@%+ STATUSMSG&lt;span style="color:#f92672"&gt;=&lt;/span&gt;~&amp;amp;@%+ TARGMAX&lt;span style="color:#f92672"&gt;=&lt;/span&gt;NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;390&lt;/span&gt; UTF8MAPPING&lt;span style="color:#f92672"&gt;=&lt;/span&gt;rfc8265 WHOX draft/CHATHISTORY&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;100&lt;/span&gt; :are supported by this server&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;251&lt;/span&gt; kiwi-n26 :There are &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; users and &lt;span style="color:#ae81ff"&gt;4&lt;/span&gt; invisible on &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; server&lt;span style="color:#f92672"&gt;(&lt;/span&gt;s&lt;span style="color:#f92672"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;252&lt;/span&gt; kiwi-n26 &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; :IRC Operators online&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;253&lt;/span&gt; kiwi-n26 &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; :unregistered connections&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;254&lt;/span&gt; kiwi-n26 &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt; :channels formed&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;255&lt;/span&gt; kiwi-n26 :I have &lt;span style="color:#ae81ff"&gt;4&lt;/span&gt; clients and &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; servers&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;265&lt;/span&gt; kiwi-n26 &lt;span style="color:#ae81ff"&gt;4&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;4&lt;/span&gt; :Current local users 4, max &lt;span style="color:#ae81ff"&gt;4&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;266&lt;/span&gt; kiwi-n26 &lt;span style="color:#ae81ff"&gt;4&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;4&lt;/span&gt; :Current global users 4, max &lt;span style="color:#ae81ff"&gt;4&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;375&lt;/span&gt; kiwi-n26 :- oragono.test Message of the day -&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;372&lt;/span&gt; kiwi-n26 :-&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;372&lt;/span&gt; kiwi-n26 :- ▄▄▄ ▄▄▄· ▄▄ • ▐ ▄&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;372&lt;/span&gt; kiwi-n26 :- ▪ ▀▄ █·▐█ ▀█ ▐█ ▀ ▪▪ •█▌▐█▪&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;372&lt;/span&gt; kiwi-n26 :- ▄█▀▄ ▐▀▀▄ ▄█▀▀█ ▄█ ▀█▄ ▄█▀▄▪▐█▐▐▌ ▄█▀▄&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;372&lt;/span&gt; kiwi-n26 :- ▐█▌.▐▌▐█•█▌▐█ ▪▐▌▐█▄▪▐█▐█▌ ▐▌██▐█▌▐█▌.▐▌&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;372&lt;/span&gt; kiwi-n26 :- ▀█▄▀▪.▀ ▀ ▀ ▀ ·▀▀▀▀ ▀█▄▀ ▀▀ █▪ ▀█▄▀▪&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;372&lt;/span&gt; kiwi-n26 :-&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;372&lt;/span&gt; kiwi-n26 :- This is the default Oragono MOTD.&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;372&lt;/span&gt; kiwi-n26 :-&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;372&lt;/span&gt; kiwi-n26 :-&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;372&lt;/span&gt; kiwi-n26 :- If motd-formatting is enabled in the config file, you can use the dollarsign character to&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;372&lt;/span&gt; kiwi-n26 :- create special formatting such as bold, italics and color codes.&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;372&lt;/span&gt; kiwi-n26 :-&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;372&lt;/span&gt; kiwi-n26 :- For example, here are a few formatted lines &lt;span style="color:#f92672"&gt;(&lt;/span&gt;enable motd-formatting to see these in action&lt;span style="color:#f92672"&gt;)&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;372&lt;/span&gt; kiwi-n26 :-&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;372&lt;/span&gt; kiwi-n26 :- - this is bold text.&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;372&lt;/span&gt; kiwi-n26 :- - this is italics text.&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;372&lt;/span&gt; kiwi-n26 :- - this is 4red and 2blue text.&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;372&lt;/span&gt; kiwi-n26 :- - this is 4,12red text with a light blue background.&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;372&lt;/span&gt; kiwi-n26 :- - this is a normal escaped dollarsign: $&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;372&lt;/span&gt; kiwi-n26 :-&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;372&lt;/span&gt; kiwi-n26 :- And now a few fun colour charts!&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;372&lt;/span&gt; kiwi-n26 :-&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;372&lt;/span&gt; kiwi-n26 :- 1,0 &lt;span style="color:#ae81ff"&gt;00&lt;/span&gt; 0,1 &lt;span style="color:#ae81ff"&gt;01&lt;/span&gt; 0,2 &lt;span style="color:#ae81ff"&gt;02&lt;/span&gt; 0,3 &lt;span style="color:#ae81ff"&gt;03&lt;/span&gt; 1,4 &lt;span style="color:#ae81ff"&gt;04&lt;/span&gt; 0,5 &lt;span style="color:#ae81ff"&gt;05&lt;/span&gt; 0,6 &lt;span style="color:#ae81ff"&gt;06&lt;/span&gt; 1,7 &lt;span style="color:#ae81ff"&gt;07&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;372&lt;/span&gt; kiwi-n26 :- 1,8 &lt;span style="color:#ae81ff"&gt;08&lt;/span&gt; 1,9 &lt;span style="color:#ae81ff"&gt;09&lt;/span&gt; 0,10 &lt;span style="color:#ae81ff"&gt;10&lt;/span&gt; 1,11 &lt;span style="color:#ae81ff"&gt;11&lt;/span&gt; 0,12 &lt;span style="color:#ae81ff"&gt;12&lt;/span&gt; 1,13 &lt;span style="color:#ae81ff"&gt;13&lt;/span&gt; 1,14 &lt;span style="color:#ae81ff"&gt;14&lt;/span&gt; 1,15 &lt;span style="color:#ae81ff"&gt;15&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;372&lt;/span&gt; kiwi-n26 :-&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;372&lt;/span&gt; kiwi-n26 :- 0,16 &lt;span style="color:#ae81ff"&gt;16&lt;/span&gt; 0,17 &lt;span style="color:#ae81ff"&gt;17&lt;/span&gt; 0,18 &lt;span style="color:#ae81ff"&gt;18&lt;/span&gt; 0,19 &lt;span style="color:#ae81ff"&gt;19&lt;/span&gt; 0,20 &lt;span style="color:#ae81ff"&gt;20&lt;/span&gt; 0,21 &lt;span style="color:#ae81ff"&gt;21&lt;/span&gt; 0,22 &lt;span style="color:#ae81ff"&gt;22&lt;/span&gt; 0,23 &lt;span style="color:#ae81ff"&gt;23&lt;/span&gt; 0,24 &lt;span style="color:#ae81ff"&gt;24&lt;/span&gt; 0,25 &lt;span style="color:#ae81ff"&gt;25&lt;/span&gt; 0,26 &lt;span style="color:#ae81ff"&gt;26&lt;/span&gt; 0,27 &lt;span style="color:#ae81ff"&gt;27&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;372&lt;/span&gt; kiwi-n26 :- 0,28 &lt;span style="color:#ae81ff"&gt;28&lt;/span&gt; 0,29 &lt;span style="color:#ae81ff"&gt;29&lt;/span&gt; 0,30 &lt;span style="color:#ae81ff"&gt;30&lt;/span&gt; 0,31 &lt;span style="color:#ae81ff"&gt;31&lt;/span&gt; 0,32 &lt;span style="color:#ae81ff"&gt;32&lt;/span&gt; 0,33 &lt;span style="color:#ae81ff"&gt;33&lt;/span&gt; 0,34 &lt;span style="color:#ae81ff"&gt;34&lt;/span&gt; 0,35 &lt;span style="color:#ae81ff"&gt;35&lt;/span&gt; 0,36 &lt;span style="color:#ae81ff"&gt;36&lt;/span&gt; 0,37 &lt;span style="color:#ae81ff"&gt;37&lt;/span&gt; 0,38 &lt;span style="color:#ae81ff"&gt;38&lt;/span&gt; 0,39 &lt;span style="color:#ae81ff"&gt;39&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;372&lt;/span&gt; kiwi-n26 :- 0,40 &lt;span style="color:#ae81ff"&gt;40&lt;/span&gt; 0,41 &lt;span style="color:#ae81ff"&gt;41&lt;/span&gt; 0,42 &lt;span style="color:#ae81ff"&gt;42&lt;/span&gt; 0,43 &lt;span style="color:#ae81ff"&gt;43&lt;/span&gt; 0,44 &lt;span style="color:#ae81ff"&gt;44&lt;/span&gt; 0,45 &lt;span style="color:#ae81ff"&gt;45&lt;/span&gt; 0,46 &lt;span style="color:#ae81ff"&gt;46&lt;/span&gt; 0,47 &lt;span style="color:#ae81ff"&gt;47&lt;/span&gt; 0,48 &lt;span style="color:#ae81ff"&gt;48&lt;/span&gt; 0,49 &lt;span style="color:#ae81ff"&gt;49&lt;/span&gt; 0,50 &lt;span style="color:#ae81ff"&gt;50&lt;/span&gt; 0,51 &lt;span style="color:#ae81ff"&gt;51&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;372&lt;/span&gt; kiwi-n26 :- 0,52 &lt;span style="color:#ae81ff"&gt;52&lt;/span&gt; 0,53 &lt;span style="color:#ae81ff"&gt;53&lt;/span&gt; 1,54 &lt;span style="color:#ae81ff"&gt;54&lt;/span&gt; 1,55 &lt;span style="color:#ae81ff"&gt;55&lt;/span&gt; 1,56 &lt;span style="color:#ae81ff"&gt;56&lt;/span&gt; 1,57 &lt;span style="color:#ae81ff"&gt;57&lt;/span&gt; 1,58 &lt;span style="color:#ae81ff"&gt;58&lt;/span&gt; 0,59 &lt;span style="color:#ae81ff"&gt;59&lt;/span&gt; 0,60 &lt;span style="color:#ae81ff"&gt;60&lt;/span&gt; 0,61 &lt;span style="color:#ae81ff"&gt;61&lt;/span&gt; 0,62 &lt;span style="color:#ae81ff"&gt;62&lt;/span&gt; 0,63 &lt;span style="color:#ae81ff"&gt;63&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;372&lt;/span&gt; kiwi-n26 :- 0,64 &lt;span style="color:#ae81ff"&gt;64&lt;/span&gt; 1,65 &lt;span style="color:#ae81ff"&gt;65&lt;/span&gt; 1,66 &lt;span style="color:#ae81ff"&gt;66&lt;/span&gt; 1,67 &lt;span style="color:#ae81ff"&gt;67&lt;/span&gt; 1,68 &lt;span style="color:#ae81ff"&gt;68&lt;/span&gt; 1,69 &lt;span style="color:#ae81ff"&gt;69&lt;/span&gt; 1,70 &lt;span style="color:#ae81ff"&gt;70&lt;/span&gt; 1,71 &lt;span style="color:#ae81ff"&gt;71&lt;/span&gt; 0,72 &lt;span style="color:#ae81ff"&gt;72&lt;/span&gt; 0,73 &lt;span style="color:#ae81ff"&gt;73&lt;/span&gt; 0,74 &lt;span style="color:#ae81ff"&gt;74&lt;/span&gt; 0,75 &lt;span style="color:#ae81ff"&gt;75&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;372&lt;/span&gt; kiwi-n26 :- 1,76 &lt;span style="color:#ae81ff"&gt;76&lt;/span&gt; 1,77 &lt;span style="color:#ae81ff"&gt;77&lt;/span&gt; 1,78 &lt;span style="color:#ae81ff"&gt;78&lt;/span&gt; 1,79 &lt;span style="color:#ae81ff"&gt;79&lt;/span&gt; 1,80 &lt;span style="color:#ae81ff"&gt;80&lt;/span&gt; 1,81 &lt;span style="color:#ae81ff"&gt;81&lt;/span&gt; 1,82 &lt;span style="color:#ae81ff"&gt;82&lt;/span&gt; 1,83 &lt;span style="color:#ae81ff"&gt;83&lt;/span&gt; 1,84 &lt;span style="color:#ae81ff"&gt;84&lt;/span&gt; 1,85 &lt;span style="color:#ae81ff"&gt;85&lt;/span&gt; 1,86 &lt;span style="color:#ae81ff"&gt;86&lt;/span&gt; 1,87 &lt;span style="color:#ae81ff"&gt;87&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;372&lt;/span&gt; kiwi-n26 :- 0,88 &lt;span style="color:#ae81ff"&gt;88&lt;/span&gt; 0,89 &lt;span style="color:#ae81ff"&gt;89&lt;/span&gt; 0,90 &lt;span style="color:#ae81ff"&gt;90&lt;/span&gt; 0,91 &lt;span style="color:#ae81ff"&gt;91&lt;/span&gt; 0,92 &lt;span style="color:#ae81ff"&gt;92&lt;/span&gt; 0,93 &lt;span style="color:#ae81ff"&gt;93&lt;/span&gt; 0,94 &lt;span style="color:#ae81ff"&gt;94&lt;/span&gt; 0,95 &lt;span style="color:#ae81ff"&gt;95&lt;/span&gt; 1,96 &lt;span style="color:#ae81ff"&gt;96&lt;/span&gt; 1,97 &lt;span style="color:#ae81ff"&gt;97&lt;/span&gt; 1,98 &lt;span style="color:#ae81ff"&gt;98&lt;/span&gt; 99,99 &lt;span style="color:#ae81ff"&gt;99&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;372&lt;/span&gt; kiwi-n26 :-&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;372&lt;/span&gt; kiwi-n26 :- For more information on using these, see MOTDFORMATTING.md&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;376&lt;/span&gt; kiwi-n26 :End of MOTD command&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.715Z :oragono.test &lt;span style="color:#ae81ff"&gt;221&lt;/span&gt; kiwi-n26 +Zi&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;WHO kiwi-n26&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:15.649Z :oragono.test &lt;span style="color:#ae81ff"&gt;352&lt;/span&gt; kiwi-n26 * ~u gcjc79gmtbe42.irc oragono.test kiwi-n26 H :0 https://kiwiirc.com/&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:15.649Z :oragono.test &lt;span style="color:#ae81ff"&gt;315&lt;/span&gt; kiwi-n26 kiwi-n26!*@* :End of WHO list&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;JOIN &lt;span style="color:#75715e"&gt;#kiwiirc-default&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@msgid&lt;span style="color:#f92672"&gt;=&lt;/span&gt;bidkvpja5njjtgchub8u65pxgn;time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:26.706Z :kiwi-n26!~u@gcjc79gmtbe42.irc JOIN &lt;span style="color:#75715e"&gt;#kiwiirc-default * https://kiwiirc.com/&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:26.706Z :oragono.test &lt;span style="color:#ae81ff"&gt;353&lt;/span&gt; kiwi-n26 &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#75715e"&gt;#kiwiirc-default :@kiwi-n28!~u@5g96q93tqw3vn.irc kiwi-n30!~u@5g96q93tqw3vn.irc kiwi-n29!~u@5g96q93tqw3vn.irc kiwi-n26!~u@gcjc79gmtbe42.irc&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:26.706Z :oragono.test &lt;span style="color:#ae81ff"&gt;366&lt;/span&gt; kiwi-n26 &lt;span style="color:#75715e"&gt;#kiwiirc-default :End of NAMES list&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;JOIN &lt;span style="color:#75715e"&gt;#ops&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@msgid&lt;span style="color:#f92672"&gt;=&lt;/span&gt;hftqmpu4ieyjybx9bbgf4vpbia;time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:32.145Z :kiwi-n26!~u@gcjc79gmtbe42.irc JOIN &lt;span style="color:#75715e"&gt;#ops * https://kiwiirc.com/&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:32.145Z :oragono.test &lt;span style="color:#ae81ff"&gt;353&lt;/span&gt; kiwi-n26 &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#75715e"&gt;#ops :@kiwi-n28!~u@5g96q93tqw3vn.irc kiwi-n30!~u@5g96q93tqw3vn.irc kiwi-n29!~u@5g96q93tqw3vn.irc kiwi-n26!~u@gcjc79gmtbe42.irc&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:32.145Z :oragono.test &lt;span style="color:#ae81ff"&gt;366&lt;/span&gt; kiwi-n26 &lt;span style="color:#75715e"&gt;#ops :End of NAMES list&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;PRIVMSG &lt;span style="color:#75715e"&gt;#ops hello&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;PRIVMSG &lt;span style="color:#75715e"&gt;#ops :kiwi-n28 good morning&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;PRIVMSG kiwi-n28 &lt;span style="color:#f92672"&gt;=&lt;/span&gt;D&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;PING kiwitime-1605232555315&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:57:14.150Z :oragono.test PONG oragono.test kiwitime-1605232555315&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;CHATHISTORY BEFORE kiwi-n28 * &lt;span style="color:#ae81ff"&gt;50&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:57:38.462Z :oragono.test BATCH +1 chathistory kiwi-n28&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@msgid&lt;span style="color:#f92672"&gt;=&lt;/span&gt;rqdbvmytzppssc5ymp7ffhmkga;time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:56:05.705Z;batch&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; :kiwi-n26!~u@gcjc79gmtbe42.irc PRIVMSG kiwi-n28 :&lt;span style="color:#f92672"&gt;=&lt;/span&gt;D&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:57:38.462Z :oragono.test BATCH -1&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:59:08.466Z PING kiwi-n26&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;:kiwi-n26!~u@gcjc79gmtbe42.irc QUIT :Ping timeout: 2m30s&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ERROR :Ping timeout: 2m30s&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Connection closed by foreign host.&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;可以看到这些消息都带有一定的格式，客户端根据特地的格式解析就可以个性化显示来。带有符号@/：前缀的消息都是服务器推送下来的消息，反之都是客户端请求的消息。“CAP LS 302”即协商会话协议版本，随即用命令“NICK ”设置昵称（登录名），和“USER 0 * ”设置该昵称显示的用户名，最后以“CAP END”结束协商，开始会话。服务端推送过来的消息格式为时间戳+服务器+响应码+接受者昵称+消息内容，即“@time=2020-11-13T01:55:07.714Z :oragono.test 001 :Welcome to the Internet Relay Network ”，001代表欢迎信息，具体响应码可以参考&lt;a class="link" href="https://tools.ietf.org/html/rfc2812#section-5.2" target="_blank" rel="noopener"&#10; &gt;这里&lt;/a&gt;。客户端发送消息则直接发送，比如使用“JOIN #channel”加入某个频道，服务器会向该频道里的每个人广播对JOIN应的消息“@msgid=hftqmpu4ieyjybx9bbgf4vpbia;time=2020-11-13T01:55:32.145Z :@gcjc79gmtbe42.irc JOIN #channel * ”并向操作者推送频道用户列表“@time=2020-11-13T01:55:32.145Z :oragono.test 353 = #channel :@!~&lt;a class="link" href="mailto:u@5g96q93tqw3vn.irc" &gt;u@5g96q93tqw3vn.irc&lt;/a&gt; !~&lt;a class="link" href="mailto:u@5g96q93tqw3vn.irc" &gt;u@5g96q93tqw3vn.irc&lt;/a&gt; !~&lt;a class="link" href="mailto:u@5g96q93tqw3vn.irc" &gt;u@5g96q93tqw3vn.irc&lt;/a&gt;&lt;br&gt;&#10;”。Twitch则在消息的基础上加入了其他格式化控制，比如&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@badge-info&lt;span style="color:#f92672"&gt;=&lt;/span&gt;;badges&lt;span style="color:#f92672"&gt;=&lt;/span&gt;premium/1;client-nonce&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2f70a1efd6f84523d0f180cc44f76c61;color&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#75715e"&gt;#B22222;display-name=Khodeine;emotes=58765:9-19;flags=;id=50d8790f-c474-42a8-b873-2d5e8008bd52;mod=0;room-id=30220059;subscriber=0;tmi-sent-ts=1605279854692;turbo=0;user-id=49980352;user-type= :khodeine!khodeine@khodeine.tmi.twitch.tv PRIVMSG #esl_sc2 :the scvs NotLikeThis&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;会显示以一定的颜色/图标显示用户名/消息。空闲状态下IRC服务端与客户端需要维持心跳信息，比如“PING kiwitime-1605232555315”和“time=2020-11-13T01:57:14.150Z :oragono.test PONG oragono.test kiwitime-1605232555315”，否则连接会被关闭。一些常用的命令，可以看出IRC交互非常简单，&lt;a class="link" href="https://en.wikipedia.org/wiki/IRC_services" target="_blank" rel="noopener"&#10; &gt;IRC核心组件&lt;/a&gt;也不多。使用“@+dratf/typing=active TAGMSG ”显示输入状态，借助&lt;a class="link" href="https://tools.ietf.org/id/draft-oakley-irc-ctcp-01.html" target="_blank" rel="noopener"&#10; &gt;CTCP&lt;/a&gt;协议甚至可以点对点发送文件&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#使用password注册当前nickname&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;/NS REGISTER &amp;lt;your password&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#注册一个频道&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;/CS REGISTER &lt;span style="color:#75715e"&gt;#channelname&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;/CS REGISTER &lt;span style="color:#75715e"&gt;#channe&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#要去某人加入频道&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;/INVITE nickname &lt;span style="color:#75715e"&gt;#channel&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#给予某个用户频道管理权限&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;/mode +o nickname&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#认证成为管理员&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;/OPER admin &amp;lt;admin passowrd&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#在频道发送消息&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;/PRIVMSG &lt;span style="color:#75715e"&gt;#channe hello&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#给频道某人发送消息&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;/PRIVMSG &lt;span style="color:#75715e"&gt;#channe :&amp;lt;nick&amp;gt; good morning&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#给频道某人发送消息&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;/INVITE &amp;lt;nick&amp;gt; &lt;span style="color:#75715e"&gt;#channe&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#使用密码登录&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;AUTHENTICATE PLAIN&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;AUTHENTICATE +&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;AUTHENTICATE a2l3aS1uMzAAa2l3aS1uMzAAMTAyMDMwNDA&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;a class="link" href="https://thelounge.chat/" target="_blank" rel="noopener"&#10; &gt;Thelounge&lt;/a&gt;是另外一个Vue实现的web的IRC客户端，同样支持websocket。它还用express实现了服务端，支持额外的密码/LDAP登录，即先认证通过才能连接IRC服务器，它本身也可以作为一个服务代理网关，为用户提供永远在线服务/消息存储-如果一个IRC用户不在线是不能够给它发送消息的，这一点也跟XMPP不一样。&lt;br&gt;&#10;&lt;a class="link" href="https://courages.us/wp-content/uploads/2020/11/lounge_join.png" target="_blank" rel="noopener"&#10; &gt;&lt;img class="gallery-image" data-flex-basis="480px" data-flex-grow="200" height="150" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://courages.us/wp-content/uploads/2020/11/lounge_join-300x150.png" width="300"&gt;&lt;/a&gt;&lt;/p&gt;&#10;&lt;p&gt;&lt;a class="link" href="https://courages.us/wp-content/uploads/2020/11/lounge_send.png" target="_blank" rel="noopener"&#10; &gt;&lt;img class="gallery-image" data-flex-basis="431px" data-flex-grow="179" height="167" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://courages.us/wp-content/uploads/2020/11/lounge_send-300x167.png" width="300"&gt;&lt;/a&gt;&lt;br&gt;&#10;Kiwiirc和Thelounge的设计实现良好，可以作为web chat实现的参考，比如在线客服/销售。比较两个web的IRC客户端发现，他们使用的websocket库并不一样。Kiwiirc使用的是&lt;a class="link" href="https://github.com/sockjs/sockjs-client" target="_blank" rel="noopener"&#10; &gt;sockjs-client&lt;/a&gt;，一个类似websocket的JavaScript网络连接库，支持不同浏览器，能够跨域名通信，在浏览器不支持websocket的情况下退化为&lt;a class="link" href="https://www.pubnub.com/blog/http-long-polling/" target="_blank" rel="noopener"&#10; &gt;polling&lt;/a&gt;（需要&lt;a class="link" href="https://github.com/sockjs/sockjs-node" target="_blank" rel="noopener"&#10; &gt;服务端&lt;/a&gt;配合）。而Thelounge使用的是&lt;a class="link" href="https://github.com/socketio/socket.io" target="_blank" rel="noopener"&#10; &gt;socket.io&lt;/a&gt;。Socket.IO由Engine.IO发展而来，致力于为web提供实时通信能力。Socket.IO并不是WebSocket的一个实现，只是提供了类似的连接能力，需要服务端配合。两个连接库在浏览器支持websocket的情况下都可以直接与websocket服务端通信（不需要对应的库）。Kiwiirc还提供了irc-framework开发库，可以快速搭建一个IRC客户端，比如IRC Bot。至今仍然存在着许多&lt;a class="link" href="https://en.wikipedia.org/wiki/IRC_bot" target="_blank" rel="noopener"&#10; &gt;IRC聊天机器人&lt;/a&gt;，为用户提供方便/服务器报警。Twitch一个用户加入频道时甚至能收到广告！&lt;/p&gt;&#10;&lt;p&gt;Websocket提供了与其他socket一样的能力，能够持续连接和双向通讯，甚至可以服用80/443端口（nginx支持101协议升级）。它不止可以使用在web上，也可以使用在非web上面，因为能够穿透防火墙，对树莓派的远程链接支持。传统的web应用都是一应一答，这节省的服务器/客户端的资源能够不需要持续请求的话。而对于有些应用而言，比如消息通知，希望是能够持续从服务器推送的，websocket增强了它的能力，在这之前都是long polling（所以才有那些包装库）。&lt;br&gt;&#10;Http协议在tcp基础上实现，请求头里面带有host、cookie，url里面带有路径等，这样后端能够识别、路由、分发请求。而tcp并没有这些，websocket必须自己实现类似的路由分发/调用，可以在连接建立初期，鉴别授权（可以在url上面带参数token/jwt/security key），对于后续消息的应答可以在url上面指定，也可以在事件上面指定。这样实现出来似乎与http差不多，仍然有event对应route，但却可以持续交互。&lt;br&gt;&#10;再观察IRC协议也不过是对各个命令的应答，其实也跟经典web MVC差不多-使用URL映射对应的controller/action。IRC每个会话都是一个队列，join #channel命令即订阅消息，part #channel命令则是取消订阅。再看Rabbitmq消息队列，实现了exchange，route，queue，channel，topic等，然后是持续的消费/推送，与前面所诉差不多，这样子看IRC也是个消息服务器。IRC实现简单，通过扩展支持的命令，也能够与内部/外部系统结合，快速搭建一个即时消息平台。&lt;br&gt;&#10;再看邮件服务，其实也是消息服务，也有一对一/群发消息/历史消息，甚至能够给不认识（不在线）的人发送邮件！而邮件服务至今流行，在许多平台，不论服务器还是手机都自带，不需要额外安装软件。&lt;a class="link" href="https://slack.com/intl/en-cn/features" target="_blank" rel="noopener"&#10; &gt;Slack&lt;/a&gt;的产品宣传即对比了自己相对邮件服务的优势。其实手机默认带的电话和短信功能是基于硬件模块的在线功能。&lt;br&gt;&#10;相比Ejabberd/Openfire，IRC服务器的部署简单许多，甚至可以部署在树莓派上！&lt;/p&gt;&#10;&lt;p&gt;参考连接：&lt;br&gt;&#10;&lt;a class="link" href="http://IRC%20bot" target="_blank" rel="noopener"&#10; &gt;IRC Bot&lt;/a&gt;&lt;br&gt;&#10;&lt;a class="link" href="https://developer.ibm.com/zh/technologies/messaging/articles/os-cn-rabbit-mq/" target="_blank" rel="noopener"&#10; &gt;基于 RabbitMQ 的实时消息推送&lt;/a&gt;&lt;/p&gt;&#10;</description></item><item><title>即时通信XMPP服务器ejabberd/Openfire</title><link>https://courages.us/%E5%8D%B3%E6%97%B6%E9%80%9A%E4%BF%A1xmpp%E6%9C%8D%E5%8A%A1%E5%99%A8ejabberd-openfire/</link><pubDate>Thu, 05 Nov 2020 17:14:06 +0800</pubDate><guid>https://courages.us/%E5%8D%B3%E6%97%B6%E9%80%9A%E4%BF%A1xmpp%E6%9C%8D%E5%8A%A1%E5%99%A8ejabberd-openfire/</guid><description>&lt;p&gt;即时通信的需求，不仅在公共互联网上，比如微信、QQ，也在企业的内部网络，特别是与内部系统的整合，比如OA、客服系统。&lt;a class="link" href="https://zh.wikipedia.org/wiki/%E5%8F%AF%E6%89%A9%E5%B1%95%E6%B6%88%E6%81%AF%E4%B8%8E%E5%AD%98%E5%9C%A8%E5%8D%8F%E8%AE%AE" target="_blank" rel="noopener"&#10; &gt;XMPP&lt;/a&gt;，也叫扩展消息与存在协议，是一种以XML为基础的开放式即时通信协议。&lt;a class="link" href="https://xmpp.org/" target="_blank" rel="noopener"&#10; &gt;XMPP&lt;/a&gt;不但能够用来做消息通信（单聊/群聊/订阅），也可以做语音通信。XMPP甚至支持多个服务器之间互相连接，互相通信，早期Gtalk就能够与其他XMPP服务器通信。采用XMPP来开发的好处是，已经有大量的开源服务器（ejabberd、Openfire）和客户端（Spark/Smack/converse.js/XMPPFramework）实现，能够快速搭建。&lt;br&gt;&#10;&lt;a class="link" href="https://www.ejabberd.im/" target="_blank" rel="noopener"&#10; &gt;Ejabberd&lt;/a&gt;则是ProcessOne出品的，基于Erlang开发的XMPP/MQTT/SIP服务器，内置了WebSocket/文件上传支持，提供更加丰富的&lt;a class="link" href="https://docs.ejabberd.im/developer/ejabberd-api/" target="_blank" rel="noopener"&#10; &gt;REST API&lt;/a&gt;。在CentOS64下面安装Ejabberd，会安装到/etc/init.d/ejabberd，直接service start ejabberd就好了，可以使用&lt;a class="link" href="https://github.com/processone/docker-ejabberd" target="_blank" rel="noopener"&#10; &gt;docker&lt;/a&gt;快速启用&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;root@vagrant-centos64 tmp&lt;span style="color:#f92672"&gt;]&lt;/span&gt;&lt;span style="color:#75715e"&gt;# wget https://static.process-one.net/ejabberd/downloads/20.04/ejabberd-20.04-0.x86_64.rpm&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;--2020-10-29 08:26:16--  https://static.process-one.net/ejabberd/downloads/20.04/ejabberd-20.04-0.x86_64.rpm&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Resolving static.process-one.net... 13.226.36.69, 13.226.36.105, 13.226.36.34, ...&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Connecting to static.process-one.net|13.226.36.69|:443... connected.&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;HTTP request sent, awaiting response... &lt;span style="color:#ae81ff"&gt;200&lt;/span&gt; OK&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Length: &lt;span style="color:#ae81ff"&gt;18713774&lt;/span&gt; &lt;span style="color:#f92672"&gt;(&lt;/span&gt;18M&lt;span style="color:#f92672"&gt;)&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;application/x-rpm&lt;span style="color:#f92672"&gt;]&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Saving to: “ejabberd-20.04-0.x86_64.rpm”&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;100%&lt;span style="color:#f92672"&gt;[====================================================================================================================================================================================================================================&lt;/span&gt;&amp;gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt; 18,713,774  2.84M/s   in 9.1s    &#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2020-10-29 08:26:27 &lt;span style="color:#f92672"&gt;(&lt;/span&gt;1.96 MB/s&lt;span style="color:#f92672"&gt;)&lt;/span&gt; - “ejabberd-20.04-0.x86_64.rpm” saved &lt;span style="color:#f92672"&gt;[&lt;/span&gt;18713774/18713774&lt;span style="color:#f92672"&gt;]&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;root@vagrant-centos64 tmp&lt;span style="color:#f92672"&gt;]&lt;/span&gt;&lt;span style="color:#75715e"&gt;# yum localinstall ejabberd-20.04-0.x86_64.rpm&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Loaded plugins: fastestmirror&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Setting up Local Package Process&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Examining ejabberd-20.04-0.x86_64.rpm: ejabberd-20.04-0.x86_64&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Marking ejabberd-20.04-0.x86_64.rpm to be installed&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Loading mirror speeds from cached hostfile&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; * base: mirrors.163.com&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; * epel: mirror.math.princeton.edu&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; * extras: mirrors.cn99.com&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; * updates: mirrors.cn99.com&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; * webtatic: uk.repo.webtatic.com&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;phalcon_stable/signature                                                                                                                                                                                                                               |  &lt;span style="color:#ae81ff"&gt;819&lt;/span&gt; B     00:00     &#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;phalcon_stable/signature                                                                                                                                                                                                                               |  &lt;span style="color:#ae81ff"&gt;951&lt;/span&gt; B     00:00 ... &#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;phalcon_stable-source/signature                                                                                                                                                                                                                        |  &lt;span style="color:#ae81ff"&gt;819&lt;/span&gt; B     00:00     &#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;phalcon_stable-source/signature                                                                                                                                                                                                                        |  &lt;span style="color:#ae81ff"&gt;951&lt;/span&gt; B     00:00 ... &#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Resolving Dependencies&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;--&amp;gt; Running transaction check&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;---&amp;gt; Package ejabberd.x86_64 0:20.04-0 will be installed&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;--&amp;gt; Finished Dependency Resolution&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Dependencies Resolved&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;==============================================================================================================================================================================================================================================================================&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Package                                                       Arch                                                        Version                                                        Repository                                                                     Size&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;==============================================================================================================================================================================================================================================================================&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Installing:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ejabberd                                                      x86_64                                                      20.04-0                                                        /ejabberd-20.04-0.x86_64                                                       &lt;span style="color:#ae81ff"&gt;29&lt;/span&gt; M&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Transaction Summary&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;==============================================================================================================================================================================================================================================================================&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Install       &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; Package&lt;span style="color:#f92672"&gt;(&lt;/span&gt;s&lt;span style="color:#f92672"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Total size: &lt;span style="color:#ae81ff"&gt;29&lt;/span&gt; M&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Installed size: &lt;span style="color:#ae81ff"&gt;29&lt;/span&gt; M&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Is this ok &lt;span style="color:#f92672"&gt;[&lt;/span&gt;y/N&lt;span style="color:#f92672"&gt;]&lt;/span&gt;: y&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Downloading Packages:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Running rpm_check_debug&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Running Transaction Test&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Transaction Test Succeeded&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Running Transaction&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;  Installing : ejabberd-20.04-0.x86_64                                                                                                                                                                                                                                    1/1 &#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;  Verifying  : ejabberd-20.04-0.x86_64                                                                                                                                                                                                                                    1/1 &#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Installed:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;  ejabberd.x86_64 0:20.04-0                                                                                                                                                                                                                                                   &#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Complete!&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;root@vagrant-centos64 tmp&lt;span style="color:#f92672"&gt;]&lt;/span&gt;&lt;span style="color:#75715e"&gt;# ls  /etc/init.d/ejabberd&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;/etc/init.d/ejabberd&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;root@vagrant-centos64 tmp&lt;span style="color:#f92672"&gt;]&lt;/span&gt;&lt;span style="color:#75715e"&gt;# ls -la /opt/ejabberd&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;total &lt;span style="color:#ae81ff"&gt;24&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;drwxr-xr-x  &lt;span style="color:#ae81ff"&gt;5&lt;/span&gt; ejabberd ejabberd &lt;span style="color:#ae81ff"&gt;4096&lt;/span&gt; Oct &lt;span style="color:#ae81ff"&gt;29&lt;/span&gt; 08:27 .&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;drwxr-xr-x. &lt;span style="color:#ae81ff"&gt;8&lt;/span&gt; root     root     &lt;span style="color:#ae81ff"&gt;4096&lt;/span&gt; Oct &lt;span style="color:#ae81ff"&gt;29&lt;/span&gt; 08:27 ..&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;drwxr-xr-x  &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt; ejabberd ejabberd &lt;span style="color:#ae81ff"&gt;4096&lt;/span&gt; Oct &lt;span style="color:#ae81ff"&gt;29&lt;/span&gt; 08:27 conf&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;drwxr-xr-x  &lt;span style="color:#ae81ff"&gt;3&lt;/span&gt; ejabberd ejabberd &lt;span style="color:#ae81ff"&gt;4096&lt;/span&gt; Oct &lt;span style="color:#ae81ff"&gt;29&lt;/span&gt; 08:27 database&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;-r--------  &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; ejabberd ejabberd   &lt;span style="color:#ae81ff"&gt;20&lt;/span&gt; Oct &lt;span style="color:#ae81ff"&gt;29&lt;/span&gt; 00:00 .erlang.cookie&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;drwxr-xr-x  &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt; ejabberd ejabberd &lt;span style="color:#ae81ff"&gt;4096&lt;/span&gt; Oct &lt;span style="color:#ae81ff"&gt;29&lt;/span&gt; 08:27 logs&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;root@vagrant-centos64 bin&lt;span style="color:#f92672"&gt;]&lt;/span&gt;&lt;span style="color:#75715e"&gt;# service ejabberd start&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Starting ejabberd...&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;done&lt;/span&gt;.&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;root@vagrant-centos64 sql&lt;span style="color:#f92672"&gt;]&lt;/span&gt;&lt;span style="color:#75715e"&gt;# ps aux | grep ejabberd&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ejabberd 10097  0.2  7.9 &lt;span style="color:#ae81ff"&gt;1817344&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;48144&lt;/span&gt; ?       Sl   08:51   0:04 /opt/ejabberd-20.04/bin/beam.smp -K true -P &lt;span style="color:#ae81ff"&gt;250000&lt;/span&gt; -- -root /opt/ejabberd-20.04 -progname /opt/ejabberd-20.04/bin/erl -- -home /opt/ejabberd -- -sname ejabberd@localhost -smp enable -mnesia dir &lt;span style="color:#e6db74"&gt;&amp;#34;/opt/ejabberd/database/ejabberd@localhost&amp;#34;&lt;/span&gt; -ejabberd log_rate_limit &lt;span style="color:#ae81ff"&gt;100&lt;/span&gt; log_rotate_size &lt;span style="color:#ae81ff"&gt;10485760&lt;/span&gt; log_rotate_count &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; log_rotate_date &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt; -s ejabberd -noshell -noinput&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ejabberd 10105  0.0  0.0   &lt;span style="color:#ae81ff"&gt;4060&lt;/span&gt;   &lt;span style="color:#ae81ff"&gt;496&lt;/span&gt; ?        Ss   08:51   0:00 erl_child_setup &lt;span style="color:#ae81ff"&gt;1024&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ejabberd 10186  0.0  0.0   &lt;span style="color:#ae81ff"&gt;4052&lt;/span&gt;   &lt;span style="color:#ae81ff"&gt;572&lt;/span&gt; ?        Ss   08:51   0:00 /opt/ejabberd-20.04/lib/os_mon-2.4.7/priv/bin/memsup&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;root     11215  0.0  0.1 &lt;span style="color:#ae81ff"&gt;103324&lt;/span&gt;   &lt;span style="color:#ae81ff"&gt;892&lt;/span&gt; pts/4    S+   09:16   0:00 grep ejabberd&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;root@vagrant-centos64 bin&lt;span style="color:#f92672"&gt;]&lt;/span&gt;&lt;span style="color:#75715e"&gt;# netstat -apn | grep beam&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;tcp        0      &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; 127.0.0.1:7777              0.0.0.0:*                   LISTEN      10097/beam.smp      &#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;tcp        0      &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; 0.0.0.0:37617               0.0.0.0:*                   LISTEN      1599/beam           &#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;tcp        0      &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; 0.0.0.0:15672               0.0.0.0:*                   LISTEN      1599/beam           &#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;tcp        0      &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; 0.0.0.0:55672               0.0.0.0:*                   LISTEN      1599/beam           &#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;tcp        0      &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; 0.0.0.0:43674               0.0.0.0:*                   LISTEN      10097/beam.smp      &#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;tcp        0      &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; 127.0.0.1:44055             127.0.0.1:4369              ESTABLISHED 1599/beam           &#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;tcp        0      &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; 127.0.0.1:35415             127.0.0.1:4369              ESTABLISHED 10097/beam.smp      &#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;tcp        0      &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; :::5280                     :::*                        LISTEN      10097/beam.smp      &#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;tcp        0      &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; :::5443                     :::*                        LISTEN      10097/beam.smp      &#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;tcp        0      &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; :::5222                     :::*                        LISTEN      10097/beam.smp      &#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;tcp        0      &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; :::5672                     :::*                        LISTEN      1599/beam           &#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;tcp        0      &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; :::5269                     :::*                        LISTEN      10097/beam.smp      &#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;tcp        0      &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; :::1883                     :::*                        LISTEN      10097/beam.smp      &#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;unix  3      &lt;span style="color:#f92672"&gt;[&lt;/span&gt; &lt;span style="color:#f92672"&gt;]&lt;/span&gt;         STREAM     CONNECTED     &lt;span style="color:#ae81ff"&gt;1637533&lt;/span&gt; 10097/beam.smp   &#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Ejabberd自带Erlang的数据库服务Mnesia，但有一些限制建议使用第三方的比如MySQL，这样也方便第三方交互（比如认证Token）。初始化的SQL脚本在/opt/ejabberd-20.04/lib/ejabberd-20.04/priv/sql，如果只是支持单个domain的话使用mysql.sql就可以了，多domain支持使用mysql.new.sql&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;root@vagrant-centos64 sql&lt;span style="color:#f92672"&gt;]&lt;/span&gt;&lt;span style="color:#75715e"&gt;# ls&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;lite.new.sql  lite.sql  mssql.sql  mysql.new.sql  mysql.sql  pg.new.sql  pg.sql&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;root@vagrant-centos64 sql&lt;span style="color:#f92672"&gt;]&lt;/span&gt;&lt;span style="color:#75715e"&gt;# pwd&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;/opt/ejabberd-20.04/lib/ejabberd-20.04/priv/sql&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;更改为使用&lt;a class="link" href="https://docs.ejabberd.im/tutorials/mysql/" target="_blank" rel="noopener"&#10; &gt;MySQL&lt;/a&gt;存储和认证&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;root@vagrant-centos64 bin&lt;span style="color:#f92672"&gt;]&lt;/span&gt;&lt;span style="color:#75715e"&gt;# cat /opt/ejabberd/conf/ejabberd.yml&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;###&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;###&amp;#39; ejabberd configuration file&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;###&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;### The parameters used in this configuration file are explained at&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;###&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;### https://docs.ejabberd.im/admin/configuration&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;###&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;### The configuration file is written in YAML.&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;### *******************************************************&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;### ******* !!! WARNING !!! *******&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;### ******* YAML IS INDENTATION SENSITIVE *******&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;### ******* MAKE SURE YOU INDENT SECTIONS CORRECTLY *******&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;### *******************************************************&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;### Refer to http://en.wikipedia.org/wiki/YAML for the brief description.&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;###&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;hosts:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#e6db74"&gt;&amp;#34;vagrant-centos64&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;loglevel: &lt;span style="color:#ae81ff"&gt;4&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;log_rotate_size: &lt;span style="color:#ae81ff"&gt;10485760&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;log_rotate_date: &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;log_rotate_count: &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;log_rate_limit: &lt;span style="color:#ae81ff"&gt;100&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;certfiles:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#e6db74"&gt;&amp;#34;/opt/ejabberd/conf/server.pem&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;## - &amp;#34;/etc/letsencrypt/live/localhost/fullchain.pem&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;## - &amp;#34;/etc/letsencrypt/live/localhost/privkey.pem&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ca_file: &lt;span style="color:#e6db74"&gt;&amp;#34;/opt/ejabberd/conf/cacert.pem&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;listen:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; -&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; port: &lt;span style="color:#ae81ff"&gt;5222&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ip: &lt;span style="color:#e6db74"&gt;&amp;#34;::&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; module: ejabberd_c2s&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; max_stanza_size: &lt;span style="color:#ae81ff"&gt;262144&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; shaper: c2s_shaper&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; access: c2s&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; starttls_required: true&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; -&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; port: &lt;span style="color:#ae81ff"&gt;5269&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ip: &lt;span style="color:#e6db74"&gt;&amp;#34;::&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; module: ejabberd_s2s_in&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; max_stanza_size: &lt;span style="color:#ae81ff"&gt;524288&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; -&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; port: &lt;span style="color:#ae81ff"&gt;5443&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ip: &lt;span style="color:#e6db74"&gt;&amp;#34;::&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; module: ejabberd_http&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; tls: true&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; request_handlers:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;/admin&amp;#34;&lt;/span&gt;: ejabberd_web_admin&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;/api&amp;#34;&lt;/span&gt;: mod_http_api&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;/bosh&amp;#34;&lt;/span&gt;: mod_bosh&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;/captcha&amp;#34;&lt;/span&gt;: ejabberd_captcha&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;/upload&amp;#34;&lt;/span&gt;: mod_http_upload&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;/ws&amp;#34;&lt;/span&gt;: ejabberd_http_ws&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;/oauth&amp;#34;&lt;/span&gt;: ejabberd_oauth&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; -&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; port: &lt;span style="color:#ae81ff"&gt;5280&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ip: &lt;span style="color:#e6db74"&gt;&amp;#34;::&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; module: ejabberd_http&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; request_handlers:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;/admin&amp;#34;&lt;/span&gt;: ejabberd_web_admin&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; -&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; port: &lt;span style="color:#ae81ff"&gt;1883&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ip: &lt;span style="color:#e6db74"&gt;&amp;#34;::&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; module: mod_mqtt&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; backlog: &lt;span style="color:#ae81ff"&gt;1000&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;s2s_use_starttls: optional&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;acl:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; local:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; user_regexp: &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; loopback:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ip:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - 127.0.0.0/8&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - ::1/128&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - ::FFFF:127.0.0.1/128&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; admin:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; user:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#e6db74"&gt;&amp;#34;admin@vagrant-centos64&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;access_rules:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; local:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; allow: local&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; c2s:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; deny: blocked&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; allow: all&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; announce:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; allow: admin&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; configure:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; allow: admin&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; muc_create:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; allow: local&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; pubsub_createnode:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; allow: local&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; trusted_network:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; allow: loopback&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;api_permissions:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;console commands&amp;#34;&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; from:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - ejabberd_ctl&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - mod_http_api&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; who: all&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; what: &lt;span style="color:#e6db74"&gt;&amp;#34;*&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;admin access&amp;#34;&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; who:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; access:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; allow:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; acl: loopback&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; acl: admin&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; oauth:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; scope: &lt;span style="color:#e6db74"&gt;&amp;#34;ejabberd:admin&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; access:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; allow:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; acl: loopback&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; acl: admin&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; what:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#e6db74"&gt;&amp;#34;*&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#e6db74"&gt;&amp;#34;!stop&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#e6db74"&gt;&amp;#34;!start&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;public commands&amp;#34;&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; who:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ip: 127.0.0.1/8&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; what:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - status&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - connected_users_number&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;shaper:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; normal: &lt;span style="color:#ae81ff"&gt;1000&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; fast: &lt;span style="color:#ae81ff"&gt;50000&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;shaper_rules:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; max_user_sessions: &lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; max_user_offline_messages:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 5000: admin&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 100: all&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; c2s_shaper:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; none: admin&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; normal: all&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; s2s_shaper: fast&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;max_fsm_queue: &lt;span style="color:#ae81ff"&gt;10000&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;acme:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; contact: &lt;span style="color:#e6db74"&gt;&amp;#34;mailto:admin@vagrant-centos64&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ca_url: &lt;span style="color:#e6db74"&gt;&amp;#34;https://acme-v01.api.letsencrypt.org&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;modules:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; mod_adhoc: &lt;span style="color:#f92672"&gt;{}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; mod_admin_extra: &lt;span style="color:#f92672"&gt;{}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; mod_announce:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; access: announce&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; mod_avatar: &lt;span style="color:#f92672"&gt;{}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; mod_blocking: &lt;span style="color:#f92672"&gt;{}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; mod_bosh: &lt;span style="color:#f92672"&gt;{}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; mod_caps: &lt;span style="color:#f92672"&gt;{}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; mod_carboncopy: &lt;span style="color:#f92672"&gt;{}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; mod_client_state: &lt;span style="color:#f92672"&gt;{}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; mod_configure: &lt;span style="color:#f92672"&gt;{}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; mod_disco: &lt;span style="color:#f92672"&gt;{}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; mod_fail2ban: &lt;span style="color:#f92672"&gt;{}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; mod_http_api: &lt;span style="color:#f92672"&gt;{}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; mod_http_upload:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; put_url: https://@HOST@:5443/upload&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; mod_last: &lt;span style="color:#f92672"&gt;{}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; mod_mam:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;## Mnesia is limited to 2GB, better to use an SQL backend&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;## For small servers SQLite is a good fit and is very easy&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;## to configure. Uncomment this when you have SQL configured:&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;## db_type: sql&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; assume_mam_usage: true&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; default: never&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; mod_mqtt: &lt;span style="color:#f92672"&gt;{}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; mod_muc:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; access:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - allow&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; access_admin:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - allow: admin&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; access_create: muc_create&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; access_persistent: muc_create&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; access_mam:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - allow&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; default_room_options:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; allow_subscription: true &lt;span style="color:#75715e"&gt;# enable MucSub&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; mam: false&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; mod_muc_admin: &lt;span style="color:#f92672"&gt;{}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; mod_offline:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; access_max_user_messages: max_user_offline_messages&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; mod_ping: &lt;span style="color:#f92672"&gt;{}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; mod_privacy: &lt;span style="color:#f92672"&gt;{}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; mod_private: &lt;span style="color:#f92672"&gt;{}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; mod_proxy65:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; access: local&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; max_connections: &lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; mod_pubsub:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; access_createnode: pubsub_createnode&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; plugins:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - flat&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - pep&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; force_node_config:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;## Avoid buggy clients to make their bookmarks public&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; storage:bookmarks:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; access_model: whitelist&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; mod_push: &lt;span style="color:#f92672"&gt;{}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; mod_push_keepalive: &lt;span style="color:#f92672"&gt;{}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; mod_register:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;## Only accept registration requests from the &amp;#34;trusted&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;## network (see access_rules section above).&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;## Think twice before enabling registration from any&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;## address. See the Jabber SPAM Manifesto for details:&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;## https://github.com/ge0rg/jabber-spam-fighting-manifesto&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ip_access: trusted_network&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; mod_roster:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; versioning: true&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; mod_s2s_dialback: &lt;span style="color:#f92672"&gt;{}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; mod_shared_roster: &lt;span style="color:#f92672"&gt;{}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; mod_stream_mgmt:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; resend_on_timeout: if_offline&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; mod_vcard: &lt;span style="color:#f92672"&gt;{}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; mod_vcard_xupdate: &lt;span style="color:#f92672"&gt;{}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; mod_version:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; show_os: false&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;auth_method: sql&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sql_type: mysql&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sql_server: &lt;span style="color:#e6db74"&gt;&amp;#34;localhost&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sql_database: &lt;span style="color:#e6db74"&gt;&amp;#34;ejabberd&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sql_username: &lt;span style="color:#e6db74"&gt;&amp;#34;ejabberd&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sql_password: &lt;span style="color:#e6db74"&gt;&amp;#34;ejabberd&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;default_db: sql&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;## If you want to specify the port:&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#sql_port: 3306&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;### Local Variables:&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;### mode: yaml&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;### End:&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;### vim: set filetype=yaml tabstop=8&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;试着注册一下管理员&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;root@vagrant-centos64 bin&lt;span style="color:#f92672"&gt;]&lt;/span&gt;&lt;span style="color:#75715e"&gt;# ./ejabberdctl register admin1 localhost admin&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Error: cannot_register&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;失败了，这是因为hostname的关系，在ejabberd.yml配置的host并不是localhost，改一下注册的domain就好了，具体可以参考&lt;a class="link" href="https://www.ejabberd.im/node/14744/index.html" target="_blank" rel="noopener"&#10; &gt;这里&lt;/a&gt;和&lt;a class="link" href="https://github.com/processone/ejabberd/issues/2837" target="_blank" rel="noopener"&#10; &gt;这里&lt;/a&gt;&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;root@vagrant-centos64 bin&lt;span style="color:#f92672"&gt;]&lt;/span&gt;&lt;span style="color:#75715e"&gt;# ./ejabberdctl status&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;The node ejabberd@localhost is started with status: started&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;root@vagrant-centos64 logs&lt;span style="color:#f92672"&gt;]&lt;/span&gt;&lt;span style="color:#75715e"&gt;# hostname -s&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;vagrant-centos64&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;root@vagrant-centos64 bin&lt;span style="color:#f92672"&gt;]&lt;/span&gt;&lt;span style="color:#75715e"&gt;# ./ejabberdctl register admin vagrant-centos64 admin&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;User admin@vagrant-centos64 successfully registered&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;访问http://127.0.0.1:5280/admin就可以进入到管理界面了。管理界面比较简单，只能管理用户/消息/聊天室，完整的xmpp协议服务器是支持的，客户端对应实现就好了。&lt;br&gt;&#10;&lt;a class="link" href="https://courages.us/wp-content/uploads/2020/11/ejabberd_user.png" target="_blank" rel="noopener"&#10; &gt;&lt;img class="gallery-image" data-flex-basis="486px" data-flex-grow="202" height="148" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://courages.us/wp-content/uploads/2020/11/ejabberd_user-300x148.png" width="300"&gt;&lt;/a&gt;&lt;br&gt;&#10;&lt;a class="link" href="https://courages.us/wp-content/uploads/2020/11/ejabberd_message.png" target="_blank" rel="noopener"&#10; &gt;&lt;img class="gallery-image" data-flex-basis="679px" data-flex-grow="283" height="106" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://courages.us/wp-content/uploads/2020/11/ejabberd_message-300x106.png" width="300"&gt;&lt;/a&gt;&lt;a class="link" href="https://courages.us/wp-content/uploads/2020/11/ejabberd_muc.png" target="_blank" rel="noopener"&#10; &gt;&lt;img class="gallery-image" data-flex-basis="923px" data-flex-grow="384" height="78" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://courages.us/wp-content/uploads/2020/11/ejabberd_muc-300x78.png" width="300"&gt;&lt;/a&gt;&lt;br&gt;&#10;使用&lt;a class="link" href="https://conversejs.org/" target="_blank" rel="noopener"&#10; &gt;conversejs&lt;/a&gt;快速搭建一个web客户端来验证一下，创建chat.html&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-xml" data-lang="xml"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;&amp;lt;html&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;chat&lt;span style="color:#f92672"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;link&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;rel=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;stylesheet&amp;#34;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;type=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;text/css&amp;#34;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;media=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;screen&amp;#34;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;href=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;https://cdn.conversejs.org/dist/converse.min.css&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;script&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;src=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;https://cdn.conversejs.org/dist/converse.min.js&amp;#34;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;charset=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;utf-8&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; converse.initialize({&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; //bosh_service_url: &amp;#39;http://chat.vagrant-centos64.com/bosh&amp;#39;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; websocket_url: &amp;#39;wss:chat.vagrant-centos64.com/ws&amp;#39;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; //show_controlbox_by_default: true,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; view_mode: &amp;#39;fullscreen&amp;#39;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; });&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;打开浏览器，访问对应的url登录就可以看到了聊天界面了。这里使用的域名是经过nginx代理转发过的了，配置可以参考&lt;a class="link" href="https://courages.us/api-%e7%bd%91%e5%85%b3-kong/" target="_blank" rel="noopener"&#10; &gt;API 网关 Kong&lt;/a&gt;，如果使用nginx-proxy-servier需要打开Websockets Support，以便进行协议升级101 Switching Protocols。&lt;br&gt;&#10;&lt;a class="link" href="https://courages.us/wp-content/uploads/2020/11/convesejs_login.png" target="_blank" rel="noopener"&#10; &gt;&lt;img class="gallery-image" data-flex-basis="365px" data-flex-grow="152" height="197" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://courages.us/wp-content/uploads/2020/11/convesejs_login-300x197.png" width="300"&gt;&lt;/a&gt;&lt;br&gt;&#10;&lt;a class="link" href="https://courages.us/wp-content/uploads/2020/11/conversejs_one.png" target="_blank" rel="noopener"&#10; &gt;&lt;img class="gallery-image" data-flex-basis="791px" data-flex-grow="329" height="91" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://courages.us/wp-content/uploads/2020/11/conversejs_one-300x91.png" width="300"&gt;&lt;/a&gt;&lt;br&gt;&#10;&lt;a class="link" href="https://courages.us/wp-content/uploads/2020/11/conversejs_chatroom.png" target="_blank" rel="noopener"&#10; &gt;&lt;img class="gallery-image" data-flex-basis="800px" data-flex-grow="333" height="90" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://courages.us/wp-content/uploads/2020/11/conversejs_chatroom-300x90.png" width="300"&gt;&lt;/a&gt;&lt;br&gt;&#10;conversejs配置里面有两个url，一个是&lt;a class="link" href="https://conversejs.org/docs/html/setup.html#bosh-xmpp-over-http" target="_blank" rel="noopener"&#10; &gt;BOSH&lt;/a&gt;（Bidirectional-streams Over Synchronous HTTP）的，即HTTP长连接，以便通服务器即时交互，获取消息；另一个是WebSocket，基于TCP的，客户端/服务器双向通信。BOHS需要浏览器定时发起一个请求直致服务器返回消息，而WebSocket可以像其他TCP那样双向通信，灵活的多。如果服务端不支持Websocket协议升级或者连接失败conversejs会自动切换使用BOSH通信。如果使用https://www.websocket.org/echo.html来测试连接，需要遵循XMPP协议要求，先认证，否则连接会被关闭。conversejs的认证是在Websocket里面的做的，并不基于cookie之类的，所以一个浏览器打开多个聊天窗口登录不同的账户也是可以的&lt;br&gt;&#10;&lt;a class="link" href="https://courages.us/wp-content/uploads/2020/11/conversejs_con_fail.png" target="_blank" rel="noopener"&#10; &gt;&lt;img class="gallery-image" data-flex-basis="346px" data-flex-grow="144" height="208" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://courages.us/wp-content/uploads/2020/11/conversejs_con_fail-300x208.png" width="300"&gt;&lt;/a&gt;&lt;br&gt;&#10;&lt;a class="link" href="https://courages.us/wp-content/uploads/2020/11/conversejs_con_success.png" target="_blank" rel="noopener"&#10; &gt;&lt;img class="gallery-image" data-flex-basis="642px" data-flex-grow="267" height="112" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://courages.us/wp-content/uploads/2020/11/conversejs_con_success-300x112.png" width="300"&gt;&lt;/a&gt;&lt;br&gt;&#10;&lt;a class="link" href="https://courages.us/wp-content/uploads/2020/11/converjs_websocket.png" target="_blank" rel="noopener"&#10; &gt;&lt;img class="gallery-image" data-flex-basis="923px" data-flex-grow="384" height="78" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://courages.us/wp-content/uploads/2020/11/converjs_websocket-300x78.png" width="300"&gt;&lt;/a&gt;&lt;br&gt;&#10;Ejabberd支持&lt;a class="link" href="https://docs.ejabberd.im/developer/ejabberd-api/admin-api/" target="_blank" rel="noopener"&#10; &gt;REST API&lt;/a&gt;来做交互比如查看在线用户、发送消息&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;➜ chat-example git:&lt;span style="color:#f92672"&gt;(&lt;/span&gt;master&lt;span style="color:#f92672"&gt;)&lt;/span&gt; ✗ curl -k https://192.168.33.14:5443/api/connected_users&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;admin@vagrant-centos64/converse.js-16142875&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt; ➜ chat-example git:&lt;span style="color:#f92672"&gt;(&lt;/span&gt;master&lt;span style="color:#f92672"&gt;)&lt;/span&gt; ✗ curl -k https://192.168.33.14:5443/api/send_message -X POST -d &lt;span style="color:#e6db74"&gt;&amp;#39;{&amp;#34;type&amp;#34;:&amp;#34;headline&amp;#34;,&amp;#34;from&amp;#34;:&amp;#34;test@vagrant-centos64&amp;#34;,&amp;#34;to&amp;#34;:&amp;#34;admin@vagrant-centos64&amp;#34;,&amp;#34;subject&amp;#34;:&amp;#34;Restart&amp;#34;,&amp;#34;body&amp;#34;:&amp;#34;In 5 minutes&amp;#34;}&amp;#39;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;这些API将大大增加ejabberd与第三方软件的交互。虽然ejabberd支持&lt;a class="link" href="https://docs.ejabberd.im/developer/ejabberd-api/admin-api/" target="_blank" rel="noopener"&#10; &gt;OAuth认证&lt;/a&gt;，但那是以ejabberd为账户中心的认证，方便其他系统调用ejabberd功能。通常即时通信只是内部系统的一部分，账户中心部署在其他地方，所以需要ejabberd支持外部的认证。前边已经配置ejabberd为数据库认证，还可以配置为使用LDAP认证。如果不满足，还可以配置为&lt;a class="link" href="https://docs.ejabberd.im/admin/configuration/authentication/" target="_blank" rel="noopener"&#10; &gt;外部脚本认证&lt;/a&gt;或者使用第三方开发的&lt;a class="link" href="https://github.com/processone/ejabberd-contrib/tree/master/ejabberd_auth_http" target="_blank" rel="noopener"&#10; &gt;HTTP认证&lt;/a&gt;。对于简单的内部交互，可以将认证服务的token刷新到ejabberd的数据库即可。&lt;br&gt;&#10;&lt;a class="link" href="https://www.igniterealtime.org/projects/openfire/" target="_blank" rel="noopener"&#10; &gt;Openfire&lt;/a&gt;则是ignite realtime出品的Java实现的XMPP服务器，同时提供Java客户端Spark、Java开发库Smack，还提供Chrome扩展&lt;a class="link" href="https://github.com/igniterealtime/Pade" target="_blank" rel="noopener"&#10; &gt;Pade&lt;/a&gt;。Openfire提供基于web的管理界面，支持LDAP登录及数据库存储。有一些功能Openfire并不直接支持，比如API，而是以&lt;a class="link" href="https://igniterealtime.org/projects/openfire/plugins.jsp" target="_blank" rel="noopener"&#10; &gt;扩展&lt;/a&gt;的形式支持，包括用户管理/分组管理/聊天室管理/消息广播/邮件监听/WebSocket/Meeting/Sip等等。&lt;br&gt;&#10;&lt;a class="link" href="https://courages.us/wp-content/uploads/2020/11/openfire_user.png" target="_blank" rel="noopener"&#10; &gt;&lt;img class="gallery-image" data-flex-basis="774px" data-flex-grow="322" height="93" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://courages.us/wp-content/uploads/2020/11/openfire_user-300x93.png" width="300"&gt;&lt;/a&gt;&lt;br&gt;&#10;用户管理&lt;br&gt;&#10;&lt;a class="link" href="https://courages.us/wp-content/uploads/2020/11/openfire_user_group.png" target="_blank" rel="noopener"&#10; &gt;&lt;img class="gallery-image" data-flex-basis="450px" data-flex-grow="187" height="160" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://courages.us/wp-content/uploads/2020/11/openfire_user_group-300x160.png" width="300"&gt;&lt;/a&gt;&lt;br&gt;&#10;配置用户分组，可以配置部门之类的，会出现在用户的个人分组里面（Spark）&lt;br&gt;&#10;&lt;a class="link" href="https://courages.us/wp-content/uploads/2020/11/openfire_chat_session_1.png" target="_blank" rel="noopener"&#10; &gt;&lt;img class="gallery-image" data-flex-basis="808px" data-flex-grow="337" height="89" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://courages.us/wp-content/uploads/2020/11/openfire_chat_session_1-300x89.png" width="300"&gt;&lt;/a&gt;&lt;br&gt;&#10;在线会话管理，可以踢人&lt;br&gt;&#10;&lt;a class="link" href="https://courages.us/wp-content/uploads/2020/11/openfire_chat_service.png" target="_blank" rel="noopener"&#10; &gt;&lt;img class="gallery-image" data-flex-basis="447px" data-flex-grow="186" height="161" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://courages.us/wp-content/uploads/2020/11/openfire_chat_service-300x161.png" width="300"&gt;&lt;/a&gt;&lt;br&gt;&#10;&lt;a class="link" href="https://courages.us/wp-content/uploads/2020/11/openfire_chat_conference.png" target="_blank" rel="noopener"&#10; &gt;&lt;img class="gallery-image" data-flex-basis="541px" data-flex-grow="225" height="133" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://courages.us/wp-content/uploads/2020/11/openfire_chat_conference-300x133.png" width="300"&gt;&lt;/a&gt;&lt;br&gt;&#10;创建聊天室之前需要创建对应的service，默认的service叫conference。&lt;br&gt;&#10;Openfire的API并不支持OAuth/SSO，简单的1V1消息发送，聊天室消息订阅等等，需要自己基于Java扩展。&lt;br&gt;&#10;Ejabberd是采用Erlang开发的，一如消息队列服务器RabbitMQ，具有极高吞吐能力，提供REST API/XMl RPC，方便交互；Openfire则易于管理和扩展，采用哪个软件进行开发需要结合企业实际进行考量。&lt;br&gt;&#10;XMPP服务器主要提供消息聊天，对于语音服务可以使用SIP服务器实现，结合客户端&lt;a class="link" href="https://sipjs.com/" target="_blank" rel="noopener"&#10; &gt;sip.js&lt;/a&gt;，比如&lt;a class="link" href="https://collecttix.github.io/ctxSip/" target="_blank" rel="noopener"&#10; &gt;ctxSip&lt;/a&gt;。&lt;/p&gt;&#10;&lt;p&gt;参考链接：&lt;br&gt;&#10;&lt;a class="link" href="https://courages.us/tcp-udp%e6%8e%a2%e7%b4%a2/" target="_blank" rel="noopener"&#10; &gt;TCP UDP探索&lt;/a&gt;&lt;br&gt;&#10;&lt;a class="link" href="https://zh.wikipedia.org/wiki/%E5%B0%8D%E8%A9%B1%E5%95%9F%E5%8B%95%E5%8D%94%E5%AE%9A" target="_blank" rel="noopener"&#10; &gt;SIP（会话发起协议）&lt;/a&gt;&lt;/p&gt;&#10;</description></item></channel></rss>