<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="/feed.xml" rel="self" type="application/atom+xml" /><link href="/" rel="alternate" type="text/html" /><updated>2025-06-27T00:02:36-07:00</updated><id>/feed.xml</id><title type="html">Tigase</title><subtitle>Tigase creates and provides instant communication, instant messaging and instant presence software and services. Tigase XMPP Server is high performance, scalable and reliable server software which is complemented by end-user apps for all major platforms.</subtitle><author><name>Tigase</name></author><entry><title type="html">Per-application passwords in Tigase</title><link href="/blog/tigase-per-app-credentials/" rel="alternate" type="text/html" title="Per-application passwords in Tigase" /><published>2025-06-26T05:40:32-07:00</published><updated>2025-06-26T05:40:32-07:00</updated><id>/blog/tigase-per-app-credentials</id><content type="html" xml:base="/blog/tigase-per-app-credentials/"><![CDATA[<h1 id="application-passwords">Application passwords</h1>

<p>In recent versions of Tigase XMPP Server (starting with version 8.0) it is possible to create and use multiple username and password pairs to authorize connection to the single XMPP account.</p>

<p>With that in place, it is now possible to have multiple passwords for multiple clients accessing the same account that can be used to increase security of the account. Even if one of the passwords is compromised, you can still log in and block a lost or compromised device.</p>

<h2 id="adding-application-password">Adding application password</h2>

<p>To add a new username-password pair, you need to execute <code class="language-plaintext highlighter-rouge">Add user credentials</code> ad-hoc command (command node <code class="language-plaintext highlighter-rouge">auth-credentials-add</code> at <code class="language-plaintext highlighter-rouge">sess-man</code>) while logged in the XMPP account for which you want to add a new application password.</p>

<p>During execution of a command, you will be provided with a form to fill in with following fields:</p>

<ul>
  <li>The Jabber ID for the account (<code class="language-plaintext highlighter-rouge">jid</code>) - bare JID of your account</li>
  <li>Credential ID (<code class="language-plaintext highlighter-rouge">credentialId</code>) - username for the new application password</li>
  <li>Password (<code class="language-plaintext highlighter-rouge">password</code>) - a new password</li>
</ul>

<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;iq</span> <span class="na">type=</span><span class="s">'set'</span> <span class="na">to=</span><span class="s">'sess-man@example.com'</span> <span class="na">id=</span><span class="s">'sasl-app-add-1'</span><span class="nt">&gt;</span>
	<span class="nt">&lt;command</span> <span class="na">xmlns=</span><span class="s">'http://jabber.org/protocol/commands'</span> <span class="na">node=</span><span class="s">'auth-credentials-add'</span> <span class="na">action=</span><span class="s">'execute'</span><span class="nt">/&gt;</span>
<span class="nt">&lt;/iq&gt;</span>

<span class="nt">&lt;iq</span> <span class="na">type=</span><span class="s">'result'</span> <span class="na">from=</span><span class="s">'sess-man@example.com'</span> <span class="na">id=</span><span class="s">'sasl-app-add-1'</span> <span class="na">to=</span><span class="s">'user@example.com/resource-1'</span><span class="nt">&gt;</span>
	<span class="nt">&lt;command</span> <span class="na">xmlns=</span><span class="s">'http://jabber.org/protocol/commands'</span> <span class="na">node=</span><span class="s">'auth-credentials-add'</span> <span class="na">session-id=</span><span class="s">'uuid-xxxxxx'</span> <span class="na">status=</span><span class="s">'executing'</span><span class="nt">&gt;</span>
		<span class="nt">&lt;x</span> <span class="na">xmlns=</span><span class="s">'jabber:x:data'</span> <span class="na">type=</span><span class="s">'form'</span><span class="nt">&gt;</span>
			<span class="nt">&lt;title&gt;</span>Add user credentials"<span class="nt">&lt;/title&gt;</span>
			<span class="nt">&lt;field</span> <span class="na">var=</span><span class="s">'jid'</span> <span class="na">label=</span><span class="s">'The Jabber ID for the account'</span> <span class="na">type=</span><span class="s">'jid-single'</span><span class="nt">/&gt;</span>
			<span class="nt">&lt;field</span> <span class="na">var=</span><span class="s">'credentialId'</span> <span class="na">label=</span><span class="s">'Credential ID'</span> <span class="na">type=</span><span class="s">'jid-single'</span><span class="nt">/&gt;</span>
			<span class="nt">&lt;field</span> <span class="na">var=</span><span class="s">'password'</span> <span class="na">label=</span><span class="s">'Password'</span> <span class="na">type=</span><span class="s">'text-single'</span><span class="nt">/&gt;</span>
		<span class="nt">&lt;/x&gt;</span>
	<span class="nt">&lt;/command&gt;</span>
<span class="nt">&lt;/iq&gt;</span>
</code></pre></div></div>

<p>After submitting this form a new credential will be added.</p>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;iq</span> <span class="na">type=</span><span class="s">'set'</span> <span class="na">to=</span><span class="s">'sess-man@example.com'</span> <span class="na">id=</span><span class="s">'sasl-app-add-2'</span><span class="nt">&gt;</span>
	<span class="nt">&lt;command</span> <span class="na">xmlns=</span><span class="s">'http://jabber.org/protocol/commands'</span> <span class="na">node=</span><span class="s">'auth-credentials-add'</span> <span class="na">action=</span><span class="s">'execute'</span><span class="nt">&gt;</span>
		<span class="nt">&lt;x</span> <span class="na">xmlns=</span><span class="s">'jabber:x:data'</span> <span class="na">type=</span><span class="s">'submit'</span><span class="nt">&gt;</span>
			<span class="nt">&lt;title&gt;</span>Add user credentials"<span class="nt">&lt;/title&gt;</span>
			<span class="nt">&lt;field</span> <span class="na">var=</span><span class="s">'jid'</span> <span class="na">label=</span><span class="s">'The Jabber ID for the account'</span> <span class="na">type=</span><span class="s">'jid-single'</span><span class="nt">&gt;</span>
				<span class="nt">&lt;value&gt;</span>user@example.com<span class="nt">&lt;/value&gt;</span>
			<span class="nt">&lt;/field&gt;</span>
			<span class="nt">&lt;field</span> <span class="na">var=</span><span class="s">'credentialId'</span> <span class="na">label=</span><span class="s">'Credential ID'</span> <span class="na">type=</span><span class="s">'jid-single'</span><span class="nt">&gt;</span>
				<span class="nt">&lt;value&gt;</span>my-new-app-1<span class="nt">&lt;/value&gt;</span>
			<span class="nt">&lt;/field&gt;</span>
			<span class="nt">&lt;field</span> <span class="na">var=</span><span class="s">'password'</span> <span class="na">label=</span><span class="s">'Password'</span> <span class="na">type=</span><span class="s">'text-single'</span><span class="nt">&gt;</span>
				<span class="nt">&lt;value&gt;</span>39jfnwu053743<span class="nt">&lt;/value&gt;</span>
			<span class="nt">&lt;/field&gt;</span>
		<span class="nt">&lt;/x&gt;</span>
	<span class="nt">&lt;/command&gt;</span>
<span class="nt">&lt;/iq&gt;</span>

<span class="nt">&lt;iq</span> <span class="na">type=</span><span class="s">'result'</span> <span class="na">from=</span><span class="s">'sess-man@example.com'</span> <span class="na">id=</span><span class="s">'sasl-app-add-2'</span> <span class="na">to=</span><span class="s">'user@example.com/resource-1'</span><span class="nt">&gt;</span>
	<span class="nt">&lt;command</span> <span class="na">xmlns=</span><span class="s">'http://jabber.org/protocol/commands'</span> <span class="na">node=</span><span class="s">'auth-credentials-add'</span> <span class="na">session-id=</span><span class="s">'uuid-xxxxxx'</span> <span class="na">status=</span><span class="s">'completed'</span><span class="nt">&gt;</span>
		<span class="nt">&lt;x</span> <span class="na">xmlns=</span><span class="s">'jabber:x:data'</span> <span class="na">type=</span><span class="s">'result'</span><span class="nt">&gt;</span>
			<span class="nt">&lt;field</span> <span class="na">type=</span><span class="s">'fixed'</span><span class="nt">&gt;</span>
				<span class="nt">&lt;value&gt;</span>OK<span class="nt">&lt;/value&gt;</span>
			<span class="nt">&lt;/field&gt;</span>
		<span class="nt">&lt;/x&gt;</span>
	<span class="nt">&lt;/command&gt;</span>
<span class="nt">&lt;/iq&gt;</span>
</code></pre></div></div>

<h2 id="login-in-with-application-password">Login in with application password</h2>

<p>To log in with new password the XMPP client can use any SASL mechanism, but it needs to provide (in the SASL message):</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">authzid</code> - account JID</li>
  <li><code class="language-plaintext highlighter-rouge">authcid</code> - username for application password</li>
  <li><code class="language-plaintext highlighter-rouge">passwd</code>  - application password</li>
</ul>

<p>With proper values, you application will be able to log in using application password.</p>

<p>In case of SASL PLAIN which has the following format (spaces should be ommited and <code class="language-plaintext highlighter-rouge">[]</code> means it is optional):
<code class="language-plaintext highlighter-rouge">[authzid] UTF8NUL authcid UTF8NUL passwd</code>
not encoded payload would look like this:
<code class="language-plaintext highlighter-rouge">user@example.com UTF8NUL my-new-app-1 UTF8NUL 39jfnwu053743</code></p>

<p>That after Base64 encoding would be presented as <code class="language-plaintext highlighter-rouge">dXNlckBleGFtcGxlLmNvbQBteS1uZXctYXBwLTEDOWpmbnd1MDUzNzQz</code> and this value can be used as a correct CData of <code class="language-plaintext highlighter-rouge">&lt;auth/&gt;</code> element:</p>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;auth</span> <span class="na">xmlns=</span><span class="s">'urn:ietf:params:xml:ns:xmpp-sasl'</span> <span class="na">mechanism=</span><span class="s">'PLAIN'</span><span class="nt">&gt;</span>dXNlckBleGFtcGxlLmNvbQBteS1uZXctYXBwLTEDOWpmbnd1MDUzNzQz<span class="nt">&lt;/auth&gt;</span>
</code></pre></div></div>

<h2 id="removing-application-password">Removing application password</h2>

<p>If your device is compromised or lost and you want to remove the application password, you need to use a different device and log in on your XMPP account.
Then you need to execute <code class="language-plaintext highlighter-rouge">Delete user credentials</code> ad-hoc command (command node <code class="language-plaintext highlighter-rouge">auth-credentials-delete</code> at <code class="language-plaintext highlighter-rouge">sess-man</code>).</p>

<p>During execution for a command you will be provided with a form to fill in with following fields:</p>

<ul>
  <li>The Jabber ID for the account (<code class="language-plaintext highlighter-rouge">jid</code>) - bare JID of your account</li>
  <li>Credential ID (<code class="language-plaintext highlighter-rouge">credentialId</code>) - username for the application password which you want to remove</li>
</ul>

<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;iq</span> <span class="na">type=</span><span class="s">'set'</span> <span class="na">to=</span><span class="s">'sess-man@example.com'</span> <span class="na">id=</span><span class="s">'sasl-app-delete-1'</span><span class="nt">&gt;</span>
	<span class="nt">&lt;command</span> <span class="na">xmlns=</span><span class="s">'http://jabber.org/protocol/commands'</span> <span class="na">node=</span><span class="s">'auth-credentials-delete'</span> <span class="na">action=</span><span class="s">'execute'</span><span class="nt">/&gt;</span>
<span class="nt">&lt;/iq&gt;</span>

<span class="nt">&lt;iq</span> <span class="na">type=</span><span class="s">'result'</span> <span class="na">from=</span><span class="s">'sess-man@example.com'</span> <span class="na">id=</span><span class="s">'sasl-app-delete-1'</span> <span class="na">to=</span><span class="s">'user@example.com/resource-1'</span><span class="nt">&gt;</span>
	<span class="nt">&lt;command</span> <span class="na">xmlns=</span><span class="s">'http://jabber.org/protocol/commands'</span> <span class="na">node=</span><span class="s">'auth-credentials-delete'</span> <span class="na">session-id=</span><span class="s">'uuid-xxxxxx'</span> <span class="na">status=</span><span class="s">'executing'</span><span class="nt">&gt;</span>
		<span class="nt">&lt;x</span> <span class="na">xmlns=</span><span class="s">'jabber:x:data'</span> <span class="na">type=</span><span class="s">'form'</span><span class="nt">&gt;</span>
			<span class="nt">&lt;title&gt;</span>Add user credentials"<span class="nt">&lt;/title&gt;</span>
			<span class="nt">&lt;field</span> <span class="na">var=</span><span class="s">'jid'</span> <span class="na">label=</span><span class="s">'The Jabber ID for the account'</span> <span class="na">type=</span><span class="s">'jid-single'</span><span class="nt">/&gt;</span>
			<span class="nt">&lt;field</span> <span class="na">var=</span><span class="s">'credentialId'</span> <span class="na">label=</span><span class="s">'Credential ID'</span> <span class="na">type=</span><span class="s">'jid-single'</span><span class="nt">/&gt;</span>
		<span class="nt">&lt;/x&gt;</span>
	<span class="nt">&lt;/command&gt;</span>
<span class="nt">&lt;/iq&gt;</span>
</code></pre></div></div>
<p>After submitting this form a credential will be removed.</p>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;iq</span> <span class="na">type=</span><span class="s">'set'</span> <span class="na">to=</span><span class="s">'sess-man@example.com'</span> <span class="na">id=</span><span class="s">'sasl-app-delete-2'</span><span class="nt">&gt;</span>
	<span class="nt">&lt;command</span> <span class="na">xmlns=</span><span class="s">'http://jabber.org/protocol/commands'</span> <span class="na">node=</span><span class="s">'auth-credentials-delete'</span> <span class="na">action=</span><span class="s">'execute'</span><span class="nt">&gt;</span>
		<span class="nt">&lt;x</span> <span class="na">xmlns=</span><span class="s">'jabber:x:data'</span> <span class="na">type=</span><span class="s">'submit'</span><span class="nt">&gt;</span>
			<span class="nt">&lt;title&gt;</span>Add user credentials"<span class="nt">&lt;/title&gt;</span>
			<span class="nt">&lt;field</span> <span class="na">var=</span><span class="s">'jid'</span> <span class="na">label=</span><span class="s">'The Jabber ID for the account'</span> <span class="na">type=</span><span class="s">'jid-single'</span><span class="nt">&gt;</span>
				<span class="nt">&lt;value&gt;</span>user@example.com<span class="nt">&lt;/value&gt;</span>
			<span class="nt">&lt;/field&gt;</span>
			<span class="nt">&lt;field</span> <span class="na">var=</span><span class="s">'credentialId'</span> <span class="na">label=</span><span class="s">'Credential ID'</span> <span class="na">type=</span><span class="s">'jid-single'</span><span class="nt">&gt;</span>
				<span class="nt">&lt;value&gt;</span>my-new-app-1<span class="nt">&lt;/value&gt;</span>
			<span class="nt">&lt;/field&gt;</span>
		<span class="nt">&lt;/x&gt;</span>
	<span class="nt">&lt;/command&gt;</span>
<span class="nt">&lt;/iq&gt;</span>

<span class="nt">&lt;iq</span> <span class="na">type=</span><span class="s">'result'</span> <span class="na">from=</span><span class="s">'sess-man@example.com'</span> <span class="na">id=</span><span class="s">'sasl-app-delete-2'</span> <span class="na">to=</span><span class="s">'user@example.com/resource-1'</span><span class="nt">&gt;</span>
	<span class="nt">&lt;command</span> <span class="na">xmlns=</span><span class="s">'http://jabber.org/protocol/commands'</span> <span class="na">node=</span><span class="s">'auth-credentials-delete'</span> <span class="na">session-id=</span><span class="s">'uuid-xxxxxx'</span> <span class="na">status=</span><span class="s">'completed'</span><span class="nt">&gt;</span>
		<span class="nt">&lt;x</span> <span class="na">xmlns=</span><span class="s">'jabber:x:data'</span> <span class="na">type=</span><span class="s">'result'</span><span class="nt">&gt;</span>
			<span class="nt">&lt;field</span> <span class="na">type=</span><span class="s">'fixed'</span><span class="nt">&gt;</span>
				<span class="nt">&lt;value&gt;</span>OK<span class="nt">&lt;/value&gt;</span>
			<span class="nt">&lt;/field&gt;</span>
		<span class="nt">&lt;/x&gt;</span>
	<span class="nt">&lt;/command&gt;</span>
<span class="nt">&lt;/iq&gt;</span>
</code></pre></div></div>]]></content><author><name>Tigase</name></author><category term="blog" /><category term="server" /><category term="security" /><summary type="html"><![CDATA[Better security and control over connected devices]]></summary></entry><entry><title type="html">Tigase-XMPP Server 8.4.0 released</title><link href="/blog/tigase-xmpp-server-8.4.0/" rel="alternate" type="text/html" title="Tigase-XMPP Server 8.4.0 released" /><published>2024-06-03T05:40:32-07:00</published><updated>2024-06-03T05:40:32-07:00</updated><id>/blog/tigase-xmpp-server-8.4.0</id><content type="html" xml:base="/blog/tigase-xmpp-server-8.4.0/"><![CDATA[<p>Next minor, General Availability version of <strong>Tigase XMPP Server 8.4.0</strong> has been released</p>

<h1 id="tigase-xmpp-server-840">Tigase XMPP Server 8.4.0</h1>

<blockquote>
  <p><strong>NOTE</strong>: This version requires JDK17!</p>
</blockquote>

<blockquote>
  <p><strong>NOTE</strong>: Complete list of changes available in <a href="https://tigase.dev/tigase/_server/~milestones/11"><code class="language-plaintext highlighter-rouge">tigase-server-8.4.0</code> milestone</a></p>
</blockquote>

<h2 id="major-changes">Major Changes</h2>

<ul>
  <li>Add support for XEP-0227: Portable Import/Export Format for XMPP-IM Servers (tigase/_server/server-core#1456)</li>
  <li>Add support for showing accounts with push notifications enabled as <code class="language-plaintext highlighter-rouge">away</code> (tigase/_server/server-core#1527)</li>
  <li>Add support for banning users with support of xmppbl.org (tigase/_server/tigase-muc#156)</li>
  <li>Add support for XEP-0404: Mediated Information eXchange (MIX): JID Hidden Channels</li>
  <li>Add ad-hoc commands to manage MIX channel</li>
  <li>Initial rewrite of HTTP-API from Groovy to Java and switch to jte for templating for improve performance</li>
  <li>Add dashboard to easily manage users (tigase/_server/tigase-http-api#132)</li>
  <li>Added support for opt-in for ProtoXEP: PubSub Server Information</li>
  <li>Add support for authentication of APNS provider using P8 (tigase-push)</li>
  <li>Allow overriding default “networkaddress.cache.ttl” configuration (tigase/_server/tigase-utils#26)</li>
  <li>Deprecate MD5*CredentialsEntry (tigase/_server/server-core#1359)</li>
  <li>Add support for message retraction by admins/owners (tigase/_server/tigase-mix#34)</li>
  <li>Add support for XEP-0425: Message Moderation (tigase/_server/tigase-muc#152)</li>
</ul>

<h2 id="all-minor-features--behavior-changes">All Minor Features &amp; Behavior Changes</h2>

<ul>
  <li>Fix issue where exception thrown within StoredProcedure that has transaction can cause a lock (tigase/_server/server-core#1347)</li>
  <li>Improve caching (tigase/_server/tigase-pubsub#92)</li>
  <li>Improve handling of database failovers (connecting to read-only instance due to DNS propagation being to slow on AWS part) (tigase/_server/server-core#1354)</li>
  <li>Update MongoDB driver (tigase/_server/tigase-mongodb#34)</li>
  <li>Implement support for XEP-0404: Mediated Information eXchange (MIX): JID Hidden Channels (tigase/_server/tigase-mix#37)</li>
  <li>Remove JaXMPP dependency in tigase-push-fcm (tigase/_server/tigase-push#50)</li>
  <li>Improved and refactor HTTP API implementation (tigase/_server/tigase-http-api#122)</li>
  <li>Expose account status value in endpoint to retrieve user details (tigase/_server/tigase-http-api#131)</li>
  <li>Setup not working (NPE because of missing JTE compiler) (tigase/_server/tigase-http-api#135)</li>
  <li>Add method to generate tokens/QR codes for authentication (tigase/_server/tigase-http-api#133)</li>
  <li>http-api should delay listening on port until server finished startup (tigase/_server/tigase-http-api#130)</li>
  <li>Add ad-hoc commands to manage MIX channel (tigase/_server/tigase-mix#36)</li>
  <li>Add support for exporting/importing MIX channel data (tigase/_server/tigase-mix#38)</li>
  <li>Add support for XEP-0227: Portable Import/Export Format (tigase/_server/tigase-message-archiving#81)</li>
  <li>XEP-0227: Portable Import/Export Format for XMPP-IM Servers (tigase/_server/tigase-pubsub#138)</li>
  <li>Fix disco#items of PubSub node ignores permission checking (tigase/_server/tigase-pubsub#137)</li>
  <li>NumberFormatException: For input string: “max” (tigase/_server/tigase-pubsub#134)</li>
  <li>RSM sends <max></max> element in response (tigase/_server/tigase-utils#27)</li>
  <li>Unexpected <code class="language-plaintext highlighter-rouge">&lt;build/&gt;</code> element in XEP-0092: Software Version (tigase/_server/server-core#1522)</li>
  <li>Add support for exporting MUC rooms and history to XML (tigase/_server/tigase-muc#161)</li>
  <li>Registration captcha makes registration impossible (tigase/_server/server-core#1510)</li>
  <li>Return better SASL error for accounts pending confirmation (tigase/_server/server-core#1511)</li>
  <li>Missing escaping of some chars in encrypted Push Notifications (tigase/_server/server-core#1512)</li>
  <li>SCRAM *-PLUS mechanisms unavailable after StartTLS (tigase/_server/server-core#1508)</li>
  <li>Rename ‘captcha’ field to ‘qa’ (tigase/_server/server-core#1516)</li>
  <li>Added support for opt-in for ProtoXEP: PubSub Server Information (tigase/_server/server-core#1515)</li>
  <li>Adjust TLS ciphers and options values used by default (tigase/_server/server-core#1517)</li>
  <li>Add support for token/HMAC based authentication (tigase/_server/server-core#1520)</li>
  <li>Not XML-well-formed stanza being accepted by server and routed to recipient (tigase/_server/tigase-xmltools#16)</li>
  <li>Dockerize with Jib (tigase/_server/tigase-xmpp-server-docker#12)</li>
  <li>Fix issue where it’s not possible to configure seeOtherHost.defaultHost (tigase/_server/server-core#1364)</li>
  <li>Add support for testing S2S connectivity over IPv6 (tigase/_server/server-core#1363)</li>
  <li>Add support for setting user as admin using REST API (tigase/_server/tigase-http-api#127)</li>
  <li>Create pre-processor that would filter out error messages (tigase/_server/server-core#1344)</li>
  <li>Make it easier to disable BruteForceLocker (tigase/_server/server-core#1345)</li>
  <li>Cache usage statistics are not collected/computed correctly (tigase/_server/tigase-pubsub#135)</li>
  <li>Improve handling for MAM:1 queries with old IDs (tigase/_server/tigase-muc#153)</li>
  <li>Undelivered stanzas are processed before stream closure commands (tigase/_server/server-core#1343)</li>
  <li>[Setup] Add support for env-variables exposed in docker start.sh script (tigase/_server/tigase-http-api#142)</li>
  <li>Add API-KEY repo implementation that would be based on environment variables (tigase/_server/tigase-http-api#97)</li>
  <li>Add support for certificates private key using <code class="language-plaintext highlighter-rouge">ecdsa</code> (tigase/_server/tigase-utils#28)</li>
</ul>

<h2 id="downloads">Downloads</h2>

<ul>
  <li><a href="https://github.com/tigase/tigase-server/releases/tag/tigase-server-8.4.0">Binaries (distribution packages)</a>:
    <ul>
      <li><a href="https://github.com/tigase/tigase-server/releases/download/tigase-server-8.4.0/tigase-server-8.4.0-b6793-dist-enterprise.tar.gz">tigase-server-8.4.0-b6793-dist-enterprise.tar.gz</a></li>
      <li><a href="https://github.com/tigase/tigase-server/releases/download/tigase-server-8.4.0/tigase-server-8.4.0-b6793-dist-enterprise.zip">tigase-server-8.4.0-b6793-dist-enterprise.zip</a></li>
      <li><a href="https://github.com/tigase/tigase-server/releases/download/tigase-server-8.4.0/tigase-server-8.4.0-b6793-dist.tar.gz">tigase-server-8.4.0-b6793-dist.tar.gz</a></li>
      <li><a href="https://github.com/tigase/tigase-server/releases/download/tigase-server-8.4.0/tigase-server-8.4.0-b6793-dist.zip">tigase-server-8.4.0-b6793-dist.zip</a></li>
    </ul>
  </li>
  <li><a href="https://hub.docker.com/r/tigase/tigase-xmpp-server/tags?name=8.4.0">Docker</a></li>
  <li><a href="https://tigase.dev/tigase/_server/tigase-server/~files/tigase-server-dist-8.4.0">Source Code</a></li>
  <li><a href="https://maven-repo.tigase.net/#artifact/tigase/tigase-server/8.4.0">Maven Artifacts</a></li>
</ul>

<h2 id="test-results">Test results</h2>

<ul>
  <li><a href="https://build.tigase.net/tests-results/tts-ng/">Tigase TTS-NG</a></li>
</ul>]]></content><author><name>Tigase</name></author><category term="blog" /><category term="server" /><category term="release" /><summary type="html"><![CDATA[New minor release of Tigase XMPP Server packed with improvements has been released.]]></summary></entry><entry><title type="html">Fast Docker multi-platform builds</title><link href="/blog/fast-docker-multi-platform-build/" rel="alternate" type="text/html" title="Fast Docker multi-platform builds" /><published>2022-12-21T00:00:00-08:00</published><updated>2022-12-21T00:00:00-08:00</updated><id>/blog/fast-docker-multi-platform-build</id><content type="html" xml:base="/blog/fast-docker-multi-platform-build/"><![CDATA[<p>Nowadays CPUs based on ARM architecture are gaining more and more popularity. Be that in the form of computing units of popular cloud providers or personal computers with the lead of the Apple M1/M2 chipsets.</p>

<p>Docker is a very convenient abstraction layer that allows ease and consistency of deployment of software. However, it requires that the image platform matches the platform on which we want to run the software. Luckily, docker has multi-platform support which allows to both run images from different platform and, via <code class="language-plaintext highlighter-rouge">buildx</code>, create images for variety of platforms. There is a small downside to it - it uses QEMU to, as name may suggest, emulate other platforms, which entails one downside - performance penalty, both when running the image as well as when creating it.</p>

<p>During recent preparation of Tigase XMPP Server 8.3 release I faced an issue where, due to introduction of <code class="language-plaintext highlighter-rouge">jlink</code> into our build pipeline to make the images smaller and more lean, additional processing made creation of multi-platform images virtually impossible.</p>

<p>Fortunately, <code class="language-plaintext highlighter-rouge">buildx</code> tool is very versatile an allows using multiple builders to create images and in addition, those builders can be remote so it’s possible to take advantage of computing instances from cloud providers to build images for platforms not native to the machine on which we run the build making the build speed native-like.</p>

<p><img src="/assets/posts/docker-multi-platform-ssh-remote.png" alt="" /></p>

<h3 id="preparing-remote-environment">Preparing remote environment</h3>

<p>There is nothing all that special when it comes to remote machine preparation - it has to have docker installed (follow <a href="https://docs.docker.com/desktop/install/linux-install/">Install on Linux</a> guide or one dedicated to partiular distribution used). One caveat is to make sure that it’s possible to use docker without <code class="language-plaintext highlighter-rouge">sudo</code> which is easily accheved by adding user to <code class="language-plaintext highlighter-rouge">docker</code> group:</p>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$sudo</span> gpasswd <span class="nt">-a</span> <span class="nv">$USER</span> docker
</code></pre></div></div>
<p>(restart of the shell session required afterwards).</p>

<p>Machine has to be accessible via <code class="language-plaintext highlighter-rouge">ssh</code>. Another caveat - because it’s not possible to specify key used it has to either be one available via SSH Agent or one of the following files: <code class="language-plaintext highlighter-rouge">id_rsa</code>, <code class="language-plaintext highlighter-rouge">id_ed25519</code>, <code class="language-plaintext highlighter-rouge">id_ecdsa</code>, <code class="language-plaintext highlighter-rouge">id_dsa</code> or <code class="language-plaintext highlighter-rouge">identity</code> under <code class="language-plaintext highlighter-rouge">~/.ssh</code>.</p>

<p>After everything is set up it’s possible to check if everything is correct byt executing <code class="language-plaintext highlighter-rouge">info</code> command:</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>docker <span class="nt">-H</span> ssh://&lt;usernane&gt;@&lt;<span class="nb">hostname</span><span class="o">&gt;</span> info
</code></pre></div></div>

<p>which should give output similar to the one below:</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Client:
 Context:    default
 Debug Mode: <span class="nb">false
 </span>Plugins:
  buildx: Docker Buildx <span class="o">(</span>Docker Inc., v0.9.1<span class="o">)</span>
  compose: Docker Compose <span class="o">(</span>Docker Inc., v2.12.2<span class="o">)</span>
  dev: Docker Dev Environments <span class="o">(</span>Docker Inc., v0.0.3<span class="o">)</span>
  extension: Manages Docker extensions <span class="o">(</span>Docker Inc., v0.2.13<span class="o">)</span>
  sbom: View the packaged-based Software Bill Of Materials <span class="o">(</span>SBOM<span class="o">)</span> <span class="k">for </span>an image <span class="o">(</span>Anchore Inc., 0.6.0<span class="o">)</span>
  scan: Docker Scan <span class="o">(</span>Docker Inc., v0.21.0<span class="o">)</span>

Server:
 Containers: 2
  Running: 1
  Paused: 0
  Stopped: 1
 Images: 2
 Server Version: 20.10.22
 Storage Driver: overlay2
  Backing Filesystem: extfs
  Supports d_type: <span class="nb">true
  </span>Native Overlay Diff: <span class="nb">true
  </span>userxattr: <span class="nb">false
 </span>Logging Driver: json-file
 Cgroup Driver: cgroupfs
 Cgroup Version: 1
 Plugins:
  Volume: <span class="nb">local
  </span>Network: bridge host ipvlan macvlan null overlay
  Log: awslogs fluentd gcplogs gelf journald json-file <span class="nb">local </span>logentries splunk syslog
 Swarm: inactive
 Runtimes: io.containerd.runc.v2 io.containerd.runtime.v1.linux runc
 Default Runtime: runc
 Init Binary: docker-init
 containerd version: 78f51771157abb6c9ed224c22013cdf09962315d
 runc version: v1.1.4-0-g5fd4c4d
 init version: de40ad0
 Security Options:
  apparmor
  seccomp
   Profile: default
 Kernel Version: 5.11.0-1022-aws
 Operating System: Ubuntu 20.04.3 LTS
 OSType: linux
 Architecture: x86_64
 CPUs: 2
 Total Memory: 1.901GiB
 Name: ip-172-31-48-98
 ID: X6BF:XU3T:QUBB:M5NY:IGEV:UAQL:6PJ5:GTGO:EBDX:73AS:UD5X:IY5A
 Docker Root Dir: /var/lib/docker
 Debug Mode: <span class="nb">false
 </span>Registry: https://index.docker.io/v1/
 Labels:
 Experimental: <span class="nb">false
 </span>Insecure Registries:
  127.0.0.0/8
 Live Restore Enabled: <span class="nb">false</span>
</code></pre></div></div>

<h3 id="preparing-local-buildx">Preparing local <code class="language-plaintext highlighter-rouge">buildx</code></h3>

<p>The catch here is to create a builder that has two nodes: one local for one architecture and then another one for another architecture.</p>

<p>Let’s add new local builder for arm64 platform (I’m running the build on MacBook with M1 chipset):</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>docker buildx create <span class="nt">--node</span> <span class="nb">local</span> <span class="nt">--name</span> local-remote-builder <span class="nt">--driver</span> docker-container <span class="nt">--platform</span> linux/arm64
</code></pre></div></div>

<p>Checking available builders with <code class="language-plaintext highlighter-rouge">docker buildx ls</code> should give following output</p>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>NAME/NODE            DRIVER/ENDPOINT             STATUS   BUILDKIT PLATFORMS
local-remote-builder docker-container
  <span class="nb">local              </span>unix:///var/run/docker.sock inactive          linux/arm64<span class="k">*</span>
</code></pre></div></div>

<p>Let’s add remote machine to builds for x86 architecture. The caveat is to use <code class="language-plaintext highlighter-rouge">--append</code>  parameter to add remote node to just created builder:</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>docker buildx create <span class="nt">--append</span> <span class="nt">--name</span> local-remote-builder <span class="nt">--node</span> remote <span class="nt">--driver</span> docker-container <span class="nt">--platform</span> linux/amd64 ssh://&lt;usernane&gt;@&lt;<span class="nb">hostname</span><span class="o">&gt;</span>
</code></pre></div></div>

<p>Available nodes at this time should include our remote builder:</p>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>docker buildx <span class="nb">ls
</span>NAME/NODE            DRIVER/ENDPOINT                                                 STATUS   BUILDKIT PLATFORMS
local-remote-builder docker-container
  <span class="nb">local              </span>unix:///var/run/docker.sock                                     inactive          linux/arm64<span class="k">*</span>
  remote             ssh://&lt;usernane&gt;@&lt;<span class="nb">hostname</span><span class="o">&gt;</span>                                     inactive          linux/amd64<span class="k">*</span>
</code></pre></div></div>

<p>Builders are still inactive so it’s essential to make sure they are properly booted before execution with</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>docker buildx inspect <span class="nt">--bootstrap</span> <span class="nt">--builder</span> local-remote-builder
</code></pre></div></div>

<p>command, yielding following ouput if everything went correctly</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">[</span>+] Building 12.2s <span class="o">(</span>2/2<span class="o">)</span> FINISHED
 <span class="o">=&gt;</span> <span class="o">[</span><span class="nb">local </span>internal] booting buildkit               2.9s
 <span class="o">=&gt;</span> <span class="o">=&gt;</span> pulling image moby/buildkit:buildx-stable-1  2.3s
 <span class="o">=&gt;</span> <span class="o">=&gt;</span> creating container buildx_buildkit_local     0.5s
 <span class="o">=&gt;</span> <span class="o">[</span>remote internal] booting buildkit              7.7s
 <span class="o">=&gt;</span> <span class="o">=&gt;</span> pulling image moby/buildkit:buildx-stable-1  1.1s
 <span class="o">=&gt;</span> <span class="o">=&gt;</span> creating container buildx_buildkit_remote    6.4s
Name:   local-remote-builder
Driver: docker-container

Nodes:
Name:      <span class="nb">local
</span>Endpoint:  unix:///var/run/docker.sock
Status:    running
Buildkit:  v0.10.5
Platforms: linux/arm64<span class="k">*</span>, linux/amd64, linux/amd64/v2, linux/riscv64, linux/ppc64le, linux/s390x, linux/386, linux/mips64le, linux/mips64, linux/arm/v7, linux/arm/v6

Name:      remote
Endpoint:  ssh://&lt;usernane&gt;@&lt;<span class="nb">hostname</span><span class="o">&gt;</span>
Status:    running
Buildkit:  v0.10.5
Platforms: linux/amd64<span class="k">*</span>, linux/amd64/v2, linux/amd64/v3, linux/386
</code></pre></div></div>

<p>The only remaining thing is to set newly created and configured builder to be used by default via</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>docker buildx use local-remote-builder
</code></pre></div></div>

<p>and with that our builder list should look like this (nodes listed as <code class="language-plaintext highlighter-rouge">running</code> and builder annotated with asterisk indicating it’s the default one):</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>docker buildx <span class="nb">ls
</span>NAME/NODE              DRIVER/ENDPOINT                                                 STATUS  BUILDKIT PLATFORMS
local-remote-builder <span class="k">*</span> docker-container
  <span class="nb">local                </span>unix:///var/run/docker.sock                                     running v0.10.5  linux/arm64<span class="k">*</span>, linux/amd64, linux/amd64/v2, linux/riscv64, linux/ppc64le, linux/s390x, linux/386, linux/mips64le, linux/mips64, linux/arm/v7, linux/arm/v6
  remote               ssh://&lt;usernane&gt;@&lt;<span class="nb">hostname</span><span class="o">&gt;</span>                                     running v0.10.5  linux/amd64<span class="k">*</span>, linux/amd64/v2, linux/amd64/v3, linux/386
</code></pre></div></div>

<h3 id="building-tigase-xmpp-server-image">Building Tigase XMPP Server image</h3>

<p>With everything in place, building latest version of Tigase XMPP Server 8.3 is a matter of executing <code class="language-plaintext highlighter-rouge">buildx build</code> command with desired target platforms:</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>docker buildx build <span class="nt">--platform</span> linux/amd64,linux/arm64  <span class="nt">-t</span> tigase/tigase-xmpp-server:<span class="k">${</span><span class="nv">VERSION</span><span class="k">}</span> <span class="nt">-f</span> <span class="k">${</span><span class="nv">VERSION</span><span class="k">}</span>/Dockerfile  <span class="nt">--no-cache</span> <span class="k">${</span><span class="nv">VERSION</span><span class="k">}</span>/
</code></pre></div></div>

<p>giving us image in less than a minute.</p>]]></content><author><name>Tigase</name></author><category term="blog" /><category term="server" /><category term="release" /><summary type="html"><![CDATA[Using buildx and remote machine to significantly improve build times of multi-platform images]]></summary></entry><entry><title type="html">BeagleIM 5.3.2 and SiskinIM 7.3.1 released</title><link href="/blog/beagleim-5.3.2-and-siskinim-7.3.1-released/" rel="alternate" type="text/html" title="BeagleIM 5.3.2 and SiskinIM 7.3.1 released" /><published>2022-12-20T00:00:00-08:00</published><updated>2022-12-20T00:00:00-08:00</updated><id>/blog/beagleim-5.3.2-and-siskinim-7.3.1-released</id><content type="html" xml:base="/blog/beagleim-5.3.2-and-siskinim-7.3.1-released/"><![CDATA[<p>New versions of XMPP clients for Apple’s mobile and desktop platforms have been released. Those are bugfix release, so they do not contain any major changes.</p>

<h2 id="common-changes">Common changes</h2>

<h3 id="changes">Changes</h3>
<ul>
  <li>Added support for blocking whole domains</li>
</ul>

<h3 id="fixes">Fixes</h3>
<ul>
  <li>Fixed memory leaks</li>
  <li>Fixed issue with MUC room creation</li>
</ul>

<h2 id="beagleim-532">BeagleIM 5.3.2</h2>

<h3 id="changes-1">Changes</h3>
<ul>
  <li>Improved performance of displaying conversation log</li>
  <li>
    <h3 id="fixes-1">Fixes</h3>
  </li>
  <li>Fixed issue with scrolling to newest entry in conversation log on macOS 13.0</li>
  <li>Fixed issue with copying of selected text in conversation log</li>
  <li>Fixed issue with revoking access to the MIX channel</li>
  <li>Fixed issue with receiving PM errors in MUC rooms with disabled PM</li>
</ul>

<h2 id="siskinim-731">SiskinIM 7.3.1</h2>

<h3 id="changes-2">Changes</h3>
<ul>
  <li>Improved reconnection reliability after client was in the background</li>
  <li>Improved StreamManagement implementation</li>
  <li>Adjusted to use Martin instead of TigaseSwift (library was renamed)</li>
</ul>

<h3 id="fixes-2">Fixes</h3>
<ul>
  <li>Fixed issue with resharing video files</li>
</ul>

<h2 id="downloads">Downloads</h2>

<p>You can download both application from their respective app-stores: <a href="https://beagle.im/">Beagle IM</a> from <a href="https://apps.apple.com/us/app/beagleim-by-tigase-inc/id1445349494">macOS appstore</a> and <a href="https://siskin.im/">Siskin IM</a> from <a href="https://itunes.apple.com/us/app/tigase-messenger/id1153516838">iOS appstore</a> and star them on GitHub: <a href="https://github.com/tigase/siskin-im">Siskin IM on GitHub</a> and <a href="https://github.com/tigase/beagle-im">Beagle IM on GitHub</a></p>

<h2 id="join-the-discussion">Join the discussion</h2>

<p>You can discuss all-things-Tigase (including our client apps) on our groupchat: <a href="xmpp:tigase@muc.tigase.org?join">tigase@muc.tigase.org</a></p>

<p><img src="/assets/posts/join-discussion-qr-code.png" alt="join-discussion-qr-code" /></p>]]></content><author><name>Tigase</name></author><category term="blog" /><category term="release" /><category term="beagleim" /><category term="siskinim" /><summary type="html"><![CDATA[New versions of our XMPP clients for Apple's mobile and desktop platforms have been released. Those are bugfix releases.]]></summary></entry><entry><title type="html">Tigase-XMPP Server 8.3.0 released</title><link href="/blog/tigase-xmpp-server-8.3.0/" rel="alternate" type="text/html" title="Tigase-XMPP Server 8.3.0 released" /><published>2022-12-19T04:40:32-08:00</published><updated>2022-12-19T04:40:32-08:00</updated><id>/blog/tigase-xmpp-server-8.3.0</id><content type="html" xml:base="/blog/tigase-xmpp-server-8.3.0/"><![CDATA[<p>Next minor, General Availability version of <strong>Tigase XMPP Server 8.3.0</strong> has been released</p>

<h1 id="tigase-xmpp-server-830">Tigase XMPP Server 8.3.0</h1>

<h2 id="major-changes">Major Changes</h2>

<ul>
  <li>Initial version of <a href="https://xeps.tigase.net/docs/meet-group-videocall/">Tigase Meet Protocol </a> - our take at SFU (Selective Forwarding Unit) group video-calls</li>
  <li>This version requires at least JDK in version 17 to run</li>
  <li>Added support for mam2#extended [#mam-73]</li>
  <li>Rework certificate generation to utilise <code class="language-plaintext highlighter-rouge">keygen</code> tool instead of using <code class="language-plaintext highlighter-rouge">sun.*</code> API unavailable under JDK17</li>
  <li>Added support for XEP-0440 SASL Channel Binding Type Capability and fixed and re-enabled <code class="language-plaintext highlighter-rouge">SCRAM-*-PLUS SASL</code> mechanisms [#server-1335]</li>
  <li>Added initial, preview support for SASL2 and Bind2 (disabled by default) - to enable, activate beans <code class="language-plaintext highlighter-rouge">'urn:xmpp:bind:0'</code> and <code class="language-plaintext highlighter-rouge">'urn:xmpp:sasl:2'</code> in <code class="language-plaintext highlighter-rouge">'sess-man'</code> [#server-1332]</li>
</ul>

<h2 id="all-minor-features--behavior-changes">All Minor Features &amp; Behavior Changes</h2>

<ul>
  <li>Increased network socket buffer from 2K to 4K to improve performance when reading data from socket. It can increase somewhat memory usage proportionally to number of concurrent user connections. It’s possible to configure size of this buffer using <code class="language-plaintext highlighter-rouge">socket-buffer-size</code> property (please see <a href="https://docs.tigase.net/en/tigase-server-8.3.0/Tigase_Administration/Properties/_properties.html#socket-buffer-size"><code class="language-plaintext highlighter-rouge">socket-buffer-size</code> documentation</a>).</li>
  <li>Add configuration to log size generated by LoggerTask in Monitor and decrease default from 1M to 50K; Disable serialisation of monitor events; #servers-372</li>
  <li>Add DOAP file; update documentation with supported features; #server-1076</li>
  <li>Fix issue with NPE in JabberIqAuth plugin when no password was presented due to missing return statement; fixed similar issue where, after closing the connection, the execution of the code wasn’t terminated in JabberIqAuth and SaslAuth plugins, #server-1317</li>
  <li>Add support for XEP-0398 to feature list and updated list of supported features; #server-1316</li>
  <li>Change try-catch statement in database schema loader to better catch edge cases; #serverdist-10</li>
  <li>Remove wildcard certificate generation (as main DN) in certificate container to avoid issues that it entails (inability to override such self-signed certificate via ad-hoc commands!). Wildcards are now properly handled by CertificateGenerateor and are included correctly as SAN in addition to DN for main domain; Fix handling “default” certificates from repository; #server-1279</li>
  <li>Change default watchdog ping from (forbidden by RFC) whitespace to xmpp; add warning if someone configures it as whitespace either way; server-1318</li>
  <li>Improve XMPPDomBuilderHandler logging; #server-1323</li>
  <li>Improved Stream Management code responsible for generating <code class="language-plaintext highlighter-rouge">&lt;r/&gt;</code> requests, #server-1324 (#150)</li>
  <li>Added <code class="language-plaintext highlighter-rouge">socket-buffer-size</code> option to <code class="language-plaintext highlighter-rouge">ConnectionManager</code> to configure <code class="language-plaintext highlighter-rouge">SO_RCVBUF</code> separately from internal network buffers, #server-1325</li>
  <li>Increased <code class="language-plaintext highlighter-rouge">socket-buffer-size</code> for client-to-server and inter-cluster connections and added documentation, #server-1325</li>
  <li>Fix <code class="language-plaintext highlighter-rouge">MAX_PAUSE</code> property name; #server-1326</li>
  <li>Updated implementation of XEP-0377: Spam Reporting, #server-1327</li>
  <li>Fixed issue with errors being sent for unexpected <iq type="result"></iq> stanzas, #server-1328</li>
  <li>Improved exceptions handling in StanzaProcessor, #server-1328</li>
  <li>Switch from jtds to MS own jdbc driver; #serverdist-12</li>
  <li>Prevent re-delivery of certain S2S packets (sasl, features, dialback, etc) as it doesn’t make sense; #server-1320</li>
  <li>Adjust log levels to avoid WARNINGS during startup for regular messages; #server-1115</li>
  <li>Add ‘active in last x’ statistic; #server-1281</li>
  <li>Include option to restart JVM on OOM (off by default)</li>
  <li>Correctly process packets from mobile queue instead of re-adding currently filtered packet; #server-1331</li>
  <li>Improvements to NativeMemoryTracking implementation with units; documentation; #server-1330</li>
  <li>Improve MAM logging; #servers-384</li>
  <li>Only count stanzas in StreamManagement; #server-1333</li>
  <li>Fixed advertisement stream features for unauthorized stream; #server-1334</li>
  <li>Fixed NPE during preparing stream features when connection is already closed, #server-1334</li>
  <li>Added initial support for SASL2 and Bind2 (preview feature, disabled by default) #server-1332</li>
  <li>Added support for XEP-0440 SASL Channel Binding Type Capability and fixed and reenabled <code class="language-plaintext highlighter-rouge">SCRAM-*-PLUS SASL</code> mechanisms; #server-1335</li>
  <li>Fixed NPE during enabling of stream resumption, #server-1332</li>
  <li>Fixed sending block/unblock presences from blocking command for domain, #server-1336</li>
  <li>Better default for <code class="language-plaintext highlighter-rouge">lastXmppPacketReceivedTime</code> member to avoid WatchDog closing connection before <code class="language-plaintext highlighter-rouge">lastXmppPacketReceivedTime</code> is set; #server-1337</li>
  <li>Add proper addressing validation in S2S connection and allow connections without <code class="language-plaintext highlighter-rouge">'from'</code> set; #server-1338</li>
</ul>

<h2 id="component-changes">Component Changes</h2>

<h3 id="tigase-muc-330">Tigase MUC 3.3.0</h3>

<ul>
  <li>Rework permission checker (ACL) to add graceful fallback to hidden room if possible; add abstrac muc test class and tests based on it; #muc-151</li>
  <li>Fix memory leak in self-ping-monitor (#muc-150) and improve collections synchronisation in module</li>
  <li>Fix discovery module (Room items could be returned if available, but it’s advised to not return it by default and only return plain result without error)</li>
</ul>

<h3 id="tigase-pubsub-510">Tigase PubSub 5.1.0</h3>

<ul>
  <li>Added support for mam2#extended; #mam-73</li>
  <li>Improving processing of presence and sending last published item; #pubsub-133</li>
  <li>Fix NPE in UnsubscribeNodeModule; #pubsub-130</li>
  <li>Fixed issue with MAM returning incorrect entries for MAM capable PubSub nodes; #pubsub-131</li>
</ul>

<h3 id="tigase-http-api-230">Tigase HTTP-API 2.3.0</h3>

<ul>
  <li>Switch from jtds to MS own jdbc driver; #serverdist-12</li>
  <li>Adjust log levels; #server-1115</li>
</ul>

<h3 id="tigase-message-archiving-310">Tigase Message Archiving 3.1.0</h3>

<ul>
  <li>Added support for mam2#extended; #mam-73</li>
  <li>Fixed issues with retrieval of archived messages stored in DerbyDB; #mam-73</li>
  <li>Adjust log levels; #server-1115</li>
  <li>Fixed issue with scheduling message retention cleanup; #mam-76</li>
  <li>Improve MAM logging; #servers-384</li>
  <li>Disabled storage of errors for sent PubSub notifications; #mam-77</li>
</ul>

<h3 id="tigase-mix-110">Tigase MIX 1.1.0</h3>

<ul>
  <li>Added support for mam2#extended; #mam-73</li>
  <li>Fixed issue with joining MIX channel using MUC; #mam-74</li>
  <li>Fixed issue with rejecting incomplete data forms for channel configuration; #mix-31</li>
</ul>

<h2 id="downloads">Downloads</h2>

<ul>
  <li><a href="https://github.com/tigase/tigase-server/releases/tag/tigase-server-8.3.0">Binaries (distribution packages)</a>:
    <ul>
      <li><a href="https://github.com/tigase/tigase-server/releases/download/tigase-server-8.3.0/tigase-server-8.3.0-b12193-dist-enterprise.tar.gz">tigase-server-8.3.0-b12193-dist-enterprise.tar.gz</a></li>
      <li><a href="https://github.com/tigase/tigase-server/releases/download/tigase-server-8.3.0/tigase-server-8.3.0-b12193-dist-enterprise.zip">tigase-server-8.3.0-b12193-dist-enterprise.zip</a></li>
      <li><a href="https://github.com/tigase/tigase-server/releases/download/tigase-server-8.3.0/tigase-server-8.3.0-b12193-dist.tar.gz">tigase-server-8.3.0-b12193-dist.tar.gz</a></li>
      <li><a href="https://github.com/tigase/tigase-server/releases/download/tigase-server-8.3.0/tigase-server-8.3.0-b12193-dist.zip">tigase-server-8.3.0-b12193-dist.zip</a></li>
    </ul>
  </li>
  <li><a href="https://hub.docker.com/r/tigase/tigase-xmpp-server/tags?name=8.3.0">Docker</a></li>
  <li><a href="https://github.com/tigase/tigase-server/tree/tigase-server-8.3.0">Source Code</a></li>
  <li><a href="https://maven-repo.tigase.net/#artifact/tigase/tigase-server/8.3.0">Maven Artifacts</a></li>
</ul>

<h2 id="test-results">Test results</h2>

<ul>
  <li><a href="https://build.tigase.net/tests-results/tts-ng/">Tigase TTS-NG</a></li>
</ul>]]></content><author><name>Tigase</name></author><category term="blog" /><category term="server" /><category term="release" /><summary type="html"><![CDATA[New minor release of Tigase XMPP Server packed with improvements has been released.]]></summary></entry><entry><title type="html">BeagleIM 4.1 and SiskinIM 6.1 released</title><link href="/blog/beagleim-4.1-and-siskin-6.1-released/" rel="alternate" type="text/html" title="BeagleIM 4.1 and SiskinIM 6.1 released" /><published>2020-11-12T00:00:00-08:00</published><updated>2020-11-12T00:00:00-08:00</updated><id>/blog/beagleim-4.1-and-siskin-6.1-released</id><content type="html" xml:base="/blog/beagleim-4.1-and-siskin-6.1-released/"><![CDATA[<p>New versions of XMPP clients for Apple’s mobile and desktop platforms have been released. The biggest change is introduction of <a href="https://xmpp.org/extensions/xep-0215.html">XEP-0215: External Service Discovery</a> which helps with establishing audio and video calls.</p>

<h2 id="beagleim">BeagleIM</h2>

<p>The stable release of BeagleIM 4.1 contains a lot of changes and stability improvements.</p>

<h3 id="new-xeps">New XEPs:</h3>
<ul>
  <li>Added support for <a href="https://xmpp.org/extensions/xep-0215.html">XEP-0215: External Service Discovery</a></li>
</ul>

<h3 id="major-changes">Major changes:</h3>
<ul>
  <li>Added shortcut for Last Message Correction with CMD+ARROW UP</li>
  <li>Added support for automatic scaling/recompression of images and videos to reduce size of shared files. (hold <code class="language-plaintext highlighter-rouge">alt</code> when sharing image file)</li>
</ul>

<p><img src="/assets/posts/beagle-image-compression.png" alt="" /></p>

<ul>
  <li>Added support for sharing multiple files with drag &amp; drop, copy &amp; paste or selection.</li>
  <li>Improved onboarding process</li>
  <li>Simplified updating account password</li>
</ul>

<p><img src="/assets/posts/beagle-password-change.png" alt="" /></p>

<ul>
  <li>Added indication for corrected and retracted messages</li>
  <li>Added support for /me command</li>
  <li>Replaced Me with actual nickname user is using on the account on which chat was opened.</li>
</ul>

<p><img src="/assets/posts/beagle-message-edit-retract.png" alt="" /></p>

<ul>
  <li>Redesigned accounts list</li>
</ul>

<p><img src="/assets/posts/beagle-accounts.png" alt="" /></p>

<ul>
  <li>Added support for displaying jabber:iq:version</li>
</ul>

<p><img src="/assets/posts/beagle-disco-version.png" alt="" /></p>

<ul>
  <li>Improved presentation of VCard data</li>
</ul>

<p><img src="/assets/posts/beagle-vcard.png" alt="" /></p>

<ul>
  <li>Rewrite of Markdown support to optimize it and fix the crash</li>
</ul>

<h3 id="fixes">Fixes</h3>
<ul>
  <li>Improved VCard support for MUC group chats</li>
  <li>Fixed issue with Reply option clearing clipboard</li>
  <li>Added dropping of errors received on message delivery confirmations not being delivered properly</li>
  <li>Fixed issue with VCard editing leading to disabled Edit button and improved UX</li>
  <li>Workaround for crash on BigSur (missing permission)</li>
  <li>Fixed issues with handling subscription requests</li>
  <li>Fixed issue with joining password protected MUC rooms</li>
  <li>Fixed another crash related to movie preview</li>
  <li>Fixed issue with right part of “new” button not being clickable</li>
  <li>Fixed issue with marking all MIX messages received while offline as read.</li>
  <li>Fixed support for domains ending with .local</li>
</ul>

<h2 id="siskinim">SiskinIM</h2>

<p>The stable release of SiskinIM 6.1 contains changes and stability improvements.</p>

<ul>
  <li>Added support for <a href="https://xmpp.org/extensions/xep-0215.html">XEP-0215: External Service Discovery</a></li>
  <li>Added support for automatic scaling/recompression of images and videos to reduce size of shared files.</li>
  <li>Added support for /me command</li>
  <li>Replaced Me with actual nickname user is using on the account on which chat was opened.</li>
  <li>Fixed issue with marking all MIX messages received while offline as read.</li>
  <li>Fixed support for domains ending with .local</li>
</ul>

<h2 id="downloads">Downloads</h2>

<p>You can download both application from their respective app-stores: <a href="https://beagle.im/">Beagle IM</a> from <a href="https://apps.apple.com/us/app/beagleim-by-tigase-inc/id1445349494">macOS appstore</a> and <a href="https://siskin.im/">Siskin IM</a> from <a href="https://itunes.apple.com/us/app/tigase-messenger/id1153516838">iOS appstore</a> and star them on GitHub: <a href="https://github.com/tigase/siskin-im">Siskin IM on GitHub</a> and <a href="https://github.com/tigase/beagle-im">Beagle IM on GitHub</a></p>

<h2 id="join-the-discussion">Join the discussion</h2>

<p>You can discuss all-things-Tigase (including our client apps) on our groupchat: <a href="xmpp:tigase@muc.tigase.org?join">tigase@muc.tigase.org</a></p>

<p><img src="/assets/posts/join-discussion-qr-code.png" alt="join-discussion-qr-code" /></p>]]></content><author><name>Tigase</name></author><category term="blog" /><category term="release" /><category term="beagleim" /><category term="siskinim" /><category term="VOIP" /><category term="Jingle" /><summary type="html"><![CDATA[New versions of our XMPP clients for Apple's mobile and desktop platforms have been released. Featuring improved support for VOIP and external service discovery.]]></summary></entry><entry><title type="html">Using STUN &amp;amp; TURN server with Tigase XMPP Server with XEP-0215 (External Service Discovery)</title><link href="/blog/tigase-server-with-stun-turn/" rel="alternate" type="text/html" title="Using STUN &amp;amp; TURN server with Tigase XMPP Server with XEP-0215 (External Service Discovery)" /><published>2020-09-15T00:00:00-07:00</published><updated>2020-09-15T00:00:00-07:00</updated><id>/blog/tigase-server-with-stun-turn</id><content type="html" xml:base="/blog/tigase-server-with-stun-turn/"><![CDATA[<p>Setting STUN and TURN server with Tigase XMPP Server is extremely easy and takes only a couple of minutes.</p>

<p>Communication with your family and friends is not only about instant chats. Audio and Video calls are quite important and sometimes, under unfavourable network configurations establishing a call may prove difficult. Luckily, with the help of <a href="https://en.wikipedia.org/wiki/STUN">STUN (Session Traversal Utilities for NAT)</a> and <a href="https://en.wikipedia.org/wiki/Traversal_Using_Relays_around_NAT">TURN (Traversal Using Relays around NAT )</a> servers it’s no longer a problem</p>

<p>In the following guide we will show how to setup TURN and STUN servers with Tigase XMPP Server, so that compatible XMPP clients will be able to use them. Our <a href="https://xmpp.cloud">xmpp.cloud installation</a> supports not only them, but also <a href="https://tigase.net/tigase-im-mix/">XMPP MIX</a></p>

<h2 id="assumptions">Assumptions</h2>
<p>We are assuming that you have installed your preferred TURN server and created an account on the TURN server for use by your XMPP server users and that you have installed and configured Tigase XMPP Server.</p>

<p>At the end of the article there is a short guide how to quickly setup CoTURN server.</p>

<h2 id="enabling-external-service-discovery">Enabling external service discovery</h2>

<blockquote>
  <p><strong><em>NOTE</em></strong>: It is required <strong>only</strong> for Tigase XMPP Server <strong>8.1.0 and earlier</strong></p>
</blockquote>

<p>First you need to edit <code class="language-plaintext highlighter-rouge">etc/config.tdsl</code> file and:</p>
<ol>
  <li>Add following line in the main section of the file:
    <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>'ext-disco' () {}
</code></pre></div>    </div>
  </li>
  <li>Add following line in the <code class="language-plaintext highlighter-rouge">sess-man</code> section of the file:
    <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>'urn:xmpp:extdisco:2' () {}
</code></pre></div>    </div>
  </li>
</ol>

<p>so that your config file would look like this:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>'ext-disco' () {}
'sess-man' () {
    'urn:xmpp:extdisco:2' () {}
}
</code></pre></div></div>

<h2 id="start-tigase-xmpp-server">Start Tigase XMPP Server</h2>
<p>After applying changes mentioned above, you need to start Tigase XMPP Server or, in case if it was running, restart it.</p>

<h2 id="open-admin-ui">Open Admin UI</h2>
<p>Open web browser and head to <code class="language-plaintext highlighter-rouge">http://&lt;your-xmpp-server-and-port&gt;/admin/</code> (for example: <a href="https://localhost:8080">https://localhost:8080</a>). When promped, log in by providing admin user credentials: bare JID (i.e.: <code class="language-plaintext highlighter-rouge">user@domain</code>) as the user and related password. Afterwards you’ll see main Web AdminUI screen:</p>

<p><img src="/assets/posts/web-admin-main-page.png" alt="" /></p>

<p>and on that screen open <strong>Configuration</strong> group on the left by clicking on it.</p>

<h2 id="add-external-turn-service">Add external TURN service</h2>
<p>After opening <strong>Configuration</strong> group (<code class="language-plaintext highlighter-rouge">1</code>) click on <strong>Add New Item</strong> (<code class="language-plaintext highlighter-rouge">2</code>) position which has <strong>ext-disco@…</strong> in its subtitle.</p>

<p>In the opened form you need to provide following detail:
<img src="/assets/posts/web-admin-add-new-turn-item.png" alt="" /></p>

<ul>
  <li><strong>Service</strong> - ID of the service which will be used for identification by Tigase XMPP Server <em>(eg. <code class="language-plaintext highlighter-rouge">turn@example.com</code>)</em></li>
  <li><strong>Service name</strong> - name of the service which may be presented to the user <em>(eg. <code class="language-plaintext highlighter-rouge">TURN server</code>)</em></li>
  <li><strong>Host</strong> - fully qualified domain name of the TURN server or its IP address <em>(eg. <code class="language-plaintext highlighter-rouge">turn.example.com</code>)</em></li>
  <li><strong>Port</strong> - port at which TURN server listens <em>(eg. <code class="language-plaintext highlighter-rouge">3478</code>)</em></li>
  <li><strong>Type</strong> - type of the server, enter <code class="language-plaintext highlighter-rouge">turn</code></li>
  <li><strong>Transport</strong> - type of transport used for communication with the server <code class="language-plaintext highlighter-rouge">udp</code> or <code class="language-plaintext highlighter-rouge">tcp</code> <em>(usually <code class="language-plaintext highlighter-rouge">udp</code> but item can be added for both)</em></li>
  <li><strong>Requires username and password</strong> - for notifying XMPP client that this service requires its username and password for XMPP service <em>(leave unchecked)</em></li>
  <li><strong>Username</strong> - username required for authentication for TURN server <em>(ie. <code class="language-plaintext highlighter-rouge">turn-user</code>)</em></li>
  <li><strong>Password</strong> - password required for authentication for TURN server <em>(ie. <code class="language-plaintext highlighter-rouge">turn-password</code>)</em></li>
</ul>

<p>After filling out the form, press <code class="language-plaintext highlighter-rouge">Submit</code> button (<code class="language-plaintext highlighter-rouge">3</code>) to send form and add a TURN server to external services for your server. Admin UI will confirm that service was added with the following result
<img src="/assets/posts/web-admin-add-new-item-confirmation.png" alt="" /></p>

<h2 id="add-external-stun-service">Add external STUN service</h2>
<p>While adding a TURN server is usually all what you need, in some cases you may want to allow your users to use also STUN. Steps are quite similar like on TURN server - after opening <strong>Configuration</strong> group (<code class="language-plaintext highlighter-rouge">1</code>) click on <strong>Add New Item</strong> (<code class="language-plaintext highlighter-rouge">2</code>) position which has <strong>ext-disco@…</strong> in its subtitle and in the opened form you need to provide following detail:
<img src="/assets/posts/web-admin-add-new-stun-item.png" alt="" /></p>

<ul>
  <li><strong>Service</strong> - ID of the service which will be used for identification by Tigase XMPP Server <em>(ie. <code class="language-plaintext highlighter-rouge">stun@example.com</code>)</em></li>
  <li><strong>Service name</strong> - name of the service which may be presented to the user <em>(eg. <code class="language-plaintext highlighter-rouge">STUN server</code>)</em></li>
  <li><strong>Host</strong> - fully qualified domain name of the STUN server or its IP address <em>(eg. <code class="language-plaintext highlighter-rouge">stun.example.com</code>)</em></li>
  <li><strong>Port</strong> - port at which TURN server listens <em>(eg. <code class="language-plaintext highlighter-rouge">3478</code>)</em></li>
  <li><strong>Type</strong> - type of the server, enter <code class="language-plaintext highlighter-rouge">stun</code></li>
  <li><strong>Transport</strong> - type of transport used for communication with the server <code class="language-plaintext highlighter-rouge">udp</code> or <code class="language-plaintext highlighter-rouge">tcp</code> <em>(usually <code class="language-plaintext highlighter-rouge">udp</code> but item can be added for both)</em></li>
  <li><strong>Requires username and password</strong> - for notifying XMPP client that this service requires its username and password for XMPP service <em>(leave unchecked)</em></li>
  <li><strong>Username</strong> - username required for authentication for STUN server <em>(if required)</em></li>
  <li><strong>Password</strong> - password required for authentication for STUN server <em>(if required)</em></li>
</ul>

<h3 id="note">Note</h3>
<p>If you are using the same server for STUN and TURN (you usually will as TURN servers usually contain STUN functionality) you will fill the following form with almost the same details *(only use different <strong>Service</strong> field value,  <strong>Type</strong> will be <code class="language-plaintext highlighter-rouge">stun</code> and most likely you will skip passing <strong>Username</strong> and <strong>Password</strong> - leaving them empty, the rest of the field values will be the same).</p>

<p>After filling out the form, press <code class="language-plaintext highlighter-rouge">Submit</code> button (<code class="language-plaintext highlighter-rouge">3</code>) to send form and add a STUN server to external services for your server. Admin UI will confirm that service was added with the following result
<img src="/assets/posts/web-admin-add-new-item-confirmation.png" alt="" /></p>

<h2 id="and-now-what">And now what?</h2>
<p>Now you have fully configured your STUN/TURN server for usage with Tigase XMPP Server allowing XMPP clients connected to your server and compatible with <a href="https://xmpp.org/extensions/xep-0215.html">XEP-0215: External Service Discovery</a> to take full advantage of your STUN/TURN server ie. by providing better VoIP experience.</p>

<h2 id="coturn-installation">CoTURN installation</h2>

<p>You can quickly setup CoTURN server using Docker. Please follow Docker installation on your operating system and then install CoTURN using <a href="https://hub.docker.com/r/instrumentisto/coturn">Docker Hub</a> (instrumentisto/coturn). The bare minimum required to run it looks like that (please update <code class="language-plaintext highlighter-rouge">realm</code> with your domain and <code class="language-plaintext highlighter-rouge">external-ip</code> with IP on which server should be accessible):</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo docker run \
    --name coturn \
    -p 3478:3478 \
    -p 3478:3478/udp \
    -p 5349:5349 \
    -p 5349:5349/udp \
    -p 49160-49200:49160-49200 \
    coturn/coturn \
    --log-file=stdout \
    --min-port=49160 \
    --max-port=49200 \
    --realm localhost \
    --user tigase:tigase \
    --lt-cred-mech \
    --fingerprint \
    --external-ip=$$(detect-external-ip)

</code></pre></div></div>

<blockquote>
  <p><em><strong>NOTE</strong></em>: It uses <code class="language-plaintext highlighter-rouge">tigase</code> as username/password and <code class="language-plaintext highlighter-rouge">localhost</code> as realm - please adjust if needed</p>
</blockquote>

<h3 id="tigase-xmpp-server-and-coturn-in-docker-compose">Tigase XMPP Server and CoTURN in Docker Compose</h3>

<p>Alternatively, you can use Docker Compose to quickly spin up complete Tigase XMPP Server with CoTURN configured - see our <a href="https://tigase.dev/tigase/_server/tigase-server/~files/master/src/main/docker/README.md#docker-compose">Docker Compose guide</a> for details.</p>]]></content><author><name>Tigase</name></author><category term="blog" /><category term="server" /><category term="installation" /><category term="stun" /><category term="turn" /><category term="audio-video" /><category term="calls" /><category term="VoIP" /><summary type="html"><![CDATA[Setting STUN and TURN server with Tigase XMPP Server is extremely easy and takes only a couple of minutes.]]></summary></entry><entry><title type="html">BeagleIM 4.0 and SiskinIM 6.0 released</title><link href="/blog/beagleim-4.0-and-siskin-6.0-released/" rel="alternate" type="text/html" title="BeagleIM 4.0 and SiskinIM 6.0 released" /><published>2020-09-04T00:00:00-07:00</published><updated>2020-09-04T00:00:00-07:00</updated><id>/blog/beagleim-4.0-and-siskin-6.0-released</id><content type="html" xml:base="/blog/beagleim-4.0-and-siskin-6.0-released/"><![CDATA[<p>New versions of XMPP clients for Apple’s mobile and desktop platforms have been released. The biggest change is introduction of XMPP MIX - the modern way of chatting in groups (if you are looking for a server where you can use this new feature be sure to check our <a href="https://tigase.net/tigase-im-mix/">xmpp.cloud installation</a>). It also significantly improves on audio/video calls.</p>

<h2 id="common-changes">Common changes</h2>

<h3 id="new-xeps">New XEPs:</h3>
<ul>
  <li>Added support for <a href="https://xmpp.org/extensions/xep-0369.html">XEP-0369: Mediated Information eXchange (MIX)</a> - significant improvement over group chats offered by MUC - less traffic and better delivery</li>
  <li>Improved VoIP connectivity by adding <a href="https://xmpp.org/extensions/xep-0353.html">XEP-0353: Jingle Message Initiation</a> (now compatible with Jingle Message Initiation used by Conversations)</li>
  <li>Added support for <a href="https://xmpp.org/extensions/xep-0308.html">XEP-0308: Last Message Correction</a> - editing sent message (relies on client compatibility)</li>
  <li>Added support for <a href="https://xmpp.org/extensions/xep-0424.html">XEP-0424: Message Retraction</a> - deleting sent messages (relies on client compatibility)</li>
  <li>Added support for quick replies - quoting messages to improve conversation flow</li>
  <li>Added support for <a href="https://xmpp.org/extensions/xep-0158.html#register">XEP-0158: CAPTCHA Forms: Extended In-Band Registration</a> - some server may ask for additional information or verification during registration - with this feature it’s possible to sign up with those servers as well</li>
</ul>

<h3 id="major-changes">Major changes</h3>
<ul>
  <li>Redesigned channel joining UI</li>
  <li>Optimized resource usage during the establishment of VoIP calls and improved quality of VoIP calls</li>
  <li>Improved Markdown support</li>
  <li>Improved message synchronization speed, reliability and add support for MAM version 2 (<a href="https://xmpp.org/extensions/xep-0313.html">XEP-0313: Message Archive Management</a>)</li>
  <li>Started using MAM for MUC history synchronization on rejoin (if possible)</li>
  <li>Improved support for CAPS (feature discovery)</li>
  <li>New chats list view with a single section for 1-1 chats and group chats</li>
  <li>Added a way to join hidden MUC rooms</li>
</ul>

<h3 id="fixes">Fixes</h3>
<ul>
  <li>Fixed issue with avatars in group chats not being properly displayed.</li>
  <li>Added workaround for possible issue with message archive synchronization if server does not send <code class="language-plaintext highlighter-rouge">&lt;complete/&gt;</code> attribute</li>
  <li>Fixed issue with channel info refresh</li>
</ul>

<h2 id="beagleim-40">BeagleIM 4.0</h2>

<h3 id="ui-adjustments">UI adjustments:</h3>

<ul>
  <li>
    <p>MIX / group chat creation streamlined</p>

    <p><img src="/assets/posts/mix-create-2.png" alt="mix-create" /></p>
  </li>
  <li>
    <p>Better VoIP connectivity</p>

    <p><img src="/assets/posts/beagle-call.png" alt="beagle-call" /></p>
  </li>
  <li>
    <p>Message Correction, Retraction and quick replies</p>

    <p><img src="/assets/posts/beagle-edit-message.png" alt="beagle-edit-message" /></p>
  </li>
</ul>

<h3 id="major-changes-1">Major changes</h3>
<ul>
  <li>Adjusted font size in chat history (message text is slightly bigger)</li>
  <li>Improved support for XMPP URI</li>
  <li>Improved behaviour of service discovery window (indentation of items, scrolling)</li>
  <li>Improved handling of responses for <code class="language-plaintext highlighter-rouge">&lt;iq/&gt;</code> requests which should fix some OMEMO key publication issues.</li>
  <li>Improved message text selection</li>
  <li>Remembers size of chats/roster windows</li>
  <li>Improved auto-completion of nicknames.</li>
  <li>Stopped downloading link previews if message with that link was received from someone outside of roster.</li>
</ul>

<h3 id="fixes-1">Fixes</h3>
<ul>
  <li>Fixed issue with respecting global settings for <em>Allow subscription</em> and <em>Request subscription</em></li>
  <li>Fixed Typo in Authorization menu</li>
  <li>Fixed issue with not showing notifications for incoming groupchat messages containing keywords</li>
  <li>Improved scrolling behavior (scrolling to found or first unread message, scrolling on the opening of a chat and concurrency issue)</li>
  <li>Fixed an issue with a chat message not being resized properly when window size was changed.</li>
  <li>Fixed issue with text color in chat history</li>
  <li>Fixed issue with invisible selection in the search dialog</li>
  <li>Added possible workaround for crashes when preview is for a movie</li>
  <li>Fixed crash when the server is not sending Content-Length for uploaded files.</li>
</ul>

<h3 id="development">Development</h3>
<ul>
  <li>Fixed issues with compilation on XCode 12</li>
  <li>Improved layout in chat logs (internal change)</li>
</ul>

<h2 id="siskinim-60">SiskinIM 6.0</h2>

<ul>
  <li>Improved detection of server features and prompting to enable them in SiskinIM</li>
  <li>Added request for background fetch on push notification and fixed crashes when push notification is tapped just after it is displayed (<a href="https://projects.tigase.net/issue/siskinim-205">#siskinim-205</a>, <a href="https://projects.tigase.net/issue/siskinim-206">#siskinim-206</a>)</li>
  <li>Fixed issue with using wrong speaker during the VoIP call (<a href="https://projects.tigase.net/issue/siskinim-211">#siskinim-211</a>)</li>
  <li>Added warning when access to microphone or camera is not granted during initialization of a video call (<a href="https://projects.tigase.net/issue/siskinim-213">#siskinim-213</a>)</li>
  <li>Improved account removal mechanism (<a href="https://projects.tigase.net/issue/siskinim-199">#siskinim-199</a>)</li>
  <li>Improved look of the QR codes (<a href="https://projects.tigase.net/issue/siskinim-195">#siskinim-195</a>)</li>
  <li>Fixed an issue with not dismissing room creation view after room is created (<a href="https://projects.tigase.net/issue/siskinim-230">#siskinim-230</a>)</li>
  <li>
    <p>Fixed an issue with encrypting files with AESGCM send to MUC rooms when default encryption is set to OMEMO (<a href="https://projects.tigase.net/issue/siskinim-237">#siskinim-237</a>)</p>

    <p><img src="/assets/posts/siskin-chat-list.png" alt="siskin-chat-list" /> <img src="/assets/posts/siskin-chat.png" alt="siskin-chat" /></p>
  </li>
</ul>

<h2 id="downloads">Downloads</h2>

<p>You can download both application from their respective app-stores: <a href="https://beagle.im/">Beagle IM</a> from <a href="https://apps.apple.com/us/app/beagleim-by-tigase-inc/id1445349494">macOS appstore</a> and <a href="https://siskin.im/">Siskin IM</a> from <a href="https://itunes.apple.com/us/app/tigase-messenger/id1153516838">iOS appstore</a> and star them on GitHub: <a href="https://github.com/tigase/siskin-im">Siskin IM on GitHub</a> and <a href="https://github.com/tigase/beagle-im">Beagle IM on GitHub</a></p>

<h2 id="join-the-discussion">Join the discussion</h2>

<p>You can discuss all-things-Tigase (including our client apps) on our groupchat: <a href="xmpp:tigase@muc.tigase.org?join">tigase@muc.tigase.org</a></p>

<p><img src="/assets/posts/join-discussion-qr-code.png" alt="join-discussion-qr-code" /></p>]]></content><author><name>Tigase</name></author><category term="blog" /><category term="release" /><category term="beagleim" /><category term="siskinim" /><category term="MIX" /><category term="VOIP" /><category term="Jingle" /><summary type="html"><![CDATA[New versions of our XMPP clients for Apple's mobile and desktop platforms have been released. Sporting future of XMPP group chats (MIX), improved VoIP and message corrections and retractions.]]></summary></entry><entry><title type="html">A look at Halcyon</title><link href="/blog/halcyon-a-look-at-halcyon/" rel="alternate" type="text/html" title="A look at Halcyon" /><published>2020-09-02T00:00:00-07:00</published><updated>2020-09-02T00:00:00-07:00</updated><id>/blog/halcyon-a-look-at-halcyon</id><content type="html" xml:base="/blog/halcyon-a-look-at-halcyon/"><![CDATA[<p>New XMPP library written in Kotlin with multiplatform goals.</p>

<h1 id="a-look-at-halcyon">A look at Halcyon</h1>

<p>Some time ago, we started developing multiplatform XMPP Library called <a href="https://github.com/tigase/halcyon">Halcyon</a> based on <a href="https://kotlinlang.org/docs/reference/multiplatform.html">Kotlin Multiplatform</a> by <a href="https://www.jetbrains.com/">Jetbrains</a>.
Our plan is to allow using the same library in different target environments: JVM, Android, JavaScript and Native.
Currently we are focused on JVM and JavaScript targets.</p>

<p>In this post we will try to show library design and example of usage.</p>

<p><img src="/assets/posts/halcyon-idea.png" alt="halcyon-idea" /></p>

<h2 id="before-you-start">Before you start</h2>

<p>Because Halcyon isn’t published in any Maven repository (yet), you need to compile it yourself. We believe, it will not be a problem.
The only two things you need to do is to clone repository and compile library:</p>

<p>```shell script
git clone https://github.com/tigase/halcyon.git
cd halcyon
./gradlew publishToMavenLocal</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>
Thats all. Now Halcyon is in your local Maven repository.

## Let's do something

We recommend using Gradle to build everything (except for towers and bridges maybe). You can also use Maven, it doesn't matter. Just use one of them, to prevent problems with dependencies. 
Here is sample `build.gradle.kts` file, the most important this is to enable kotlin plugin and include Hayclon in the list of dependencies:

```kotlin
plugins {
    java
    kotlin("jvm") version "1.3.61"
}

repositories {
    mavenLocal()
    jcenter()
    mavenCentral()
}

dependencies {
    implementation(kotlin("stdlib-jdk8"))
    implementation("tigase.halcyon:halcyon-core-jvm:0.0.1")
    testCompile("junit", "junit", "4.12")
}

configure&lt;JavaPluginConvention&gt; {
    sourceCompatibility = JavaVersion.VERSION_1_8
}
tasks {
    compileKotlin {
        kotlinOptions.jvmTarget = "1.8"
    }
    compileTestKotlin {
        kotlinOptions.jvmTarget = "1.8"
    }
}
</code></pre></div></div>

<p>Let’s add some Kotlin code:</p>

<div class="language-kotlin highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">fun</span> <span class="nf">main</span><span class="p">(</span><span class="n">args</span><span class="p">:</span> <span class="nc">Array</span><span class="p">&lt;</span><span class="nc">String</span><span class="p">&gt;)</span> <span class="p">{</span>
    <span class="kd">val</span> <span class="py">client</span> <span class="p">=</span> <span class="nc">Halcyon</span><span class="p">()</span>
    <span class="n">client</span><span class="p">.</span><span class="nf">configure</span> <span class="p">{</span>
        <span class="n">userJID</span> <span class="p">=</span> <span class="s">"user@sampleserver.org"</span><span class="p">.</span><span class="nf">toBareJID</span><span class="p">()</span>
        <span class="n">password</span> <span class="p">=</span> <span class="s">"secret"</span>
    <span class="p">}</span>
    <span class="n">client</span><span class="p">.</span><span class="nf">connectAndWait</span><span class="p">()</span>
    <span class="n">client</span><span class="p">.</span><span class="nf">disconnect</span><span class="p">()</span>
<span class="p">}</span>
</code></pre></div></div>

<p>This simple code creates XMPP client, connects to XMPP server and then disconnects.</p>

<p>To show how to work with Halcyon library, we will by adding code to this small code base.</p>

<h2 id="events">Events</h2>

<p>Halcyon is events-driven library. It means, that each part of library may publish event to <em>event bus</em> and all registered listeners will receive it.</p>

<p>Lets add some code to see what is being send and received over XMPP stream:</p>

<div class="language-kotlin highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">client</span><span class="p">.</span><span class="n">eventBus</span><span class="p">.</span><span class="n">register</span><span class="p">&lt;</span><span class="nc">ReceivedXMLElementEvent</span><span class="p">&gt;(</span><span class="nc">ReceivedXMLElementEvent</span><span class="p">.</span><span class="nc">TYPE</span><span class="p">)</span> <span class="p">{</span> <span class="n">event</span> <span class="p">-&gt;</span>
    <span class="nf">println</span><span class="p">(</span><span class="s">"&gt;&gt; ${event.element.getAsString()}"</span><span class="p">)</span>
<span class="p">}</span>
<span class="n">client</span><span class="p">.</span><span class="n">eventBus</span><span class="p">.</span><span class="n">register</span><span class="p">&lt;</span><span class="nc">SentXMLElementEvent</span><span class="p">&gt;(</span><span class="nc">SentXMLElementEvent</span><span class="p">.</span><span class="nc">TYPE</span><span class="p">)</span> <span class="p">{</span> <span class="n">event</span> <span class="p">-&gt;</span>
    <span class="nf">println</span><span class="p">(</span><span class="s">"&lt;&lt; ${event.element.getAsString()}"</span><span class="p">)</span>
<span class="p">}</span>
</code></pre></div></div>

<p>To listen for all events since the connection is started, we have to add this code before <code class="language-plaintext highlighter-rouge">client.connectAndWait()</code>.</p>

<p>All events extend class <code class="language-plaintext highlighter-rouge">tigase.halcyon.core.eventbus.Event</code>, so you can easily find them all in your favourite IDE.</p>

<p>Each module may have it’s own set of events, so please check documentation or source code of modules of interest.</p>

<h2 id="request">Request</h2>

<p>Now we will look at one of the most interesting things in XMPP: requests and responses.</p>

<p>XMPP protocol allows sending request to another entity and receive response.
Why is it so exciting? Because we can ping other clients, or ask for their local time!
Ok, stop joking. Of course above examples are true, but with request-response we can do much more than simple sending messages: we can manage our contacts list, we can manage Multi User Chatrooms, we can execute remote methods on server or other clients.</p>

<p>As an example we will ping other XMPP entity (it may be server or other client).
First we need to get <code class="language-plaintext highlighter-rouge">PingModule</code> to be able to use its request builder:</p>

<div class="language-kotlin highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">val</span> <span class="py">pingModule</span> <span class="p">=</span> <span class="n">client</span><span class="p">.</span><span class="n">getModule</span><span class="p">&lt;</span><span class="nc">PingModule</span><span class="p">&gt;(</span><span class="nc">PingModule</span><span class="p">.</span><span class="nc">TYPE</span><span class="p">)</span><span class="o">!!</span>
</code></pre></div></div>

<p>Ping module has method <code class="language-plaintext highlighter-rouge">ping()</code> which creates a <strong>request builder</strong> (note, that it doesn’t send anything yet!) configured to understand response and return it as object.
Method <code class="language-plaintext highlighter-rouge">ping()</code> has optional parameter <code class="language-plaintext highlighter-rouge">jid</code>. If is not provided, then ping will be send to the server to which the client is connected.</p>

<div class="language-kotlin highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">val</span> <span class="py">request</span> <span class="p">=</span> <span class="n">pingModule</span><span class="p">.</span><span class="nf">ping</span><span class="p">()</span>
<span class="n">request</span><span class="p">.</span><span class="nf">response</span> <span class="p">{</span> <span class="n">result</span> <span class="p">-&gt;</span>
    <span class="k">when</span> <span class="p">(</span><span class="n">result</span><span class="p">)</span> <span class="p">{</span>
        <span class="k">is</span> <span class="nc">IQResult</span><span class="p">.</span><span class="nc">Success</span> <span class="p">-&gt;</span> <span class="nf">println</span><span class="p">(</span><span class="s">"Pong in ${result.get()!!.time} ms"</span><span class="p">)</span>
        <span class="k">is</span> <span class="nc">IQResult</span><span class="p">.</span><span class="nc">Error</span> <span class="p">-&gt;</span> <span class="nf">println</span><span class="p">(</span><span class="s">"Oops! Error ${result.error}"</span><span class="p">)</span>
    <span class="p">}</span>
<span class="p">}</span>
<span class="n">request</span><span class="p">.</span><span class="nf">send</span><span class="p">()</span>
</code></pre></div></div>

<p>There is also a different way to add response handler to the request:</p>

<div class="language-kotlin highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">request</span><span class="p">.</span><span class="nf">handle</span> <span class="p">{</span>
    <span class="nf">success</span> <span class="p">{</span> <span class="n">request</span><span class="p">,</span> <span class="n">iq</span><span class="p">,</span> <span class="n">result</span> <span class="p">-&gt;</span> <span class="nf">println</span><span class="p">(</span><span class="s">"Pong in ${result!!.time} ms"</span><span class="p">)</span> <span class="p">}</span>
    <span class="nf">error</span> <span class="p">{</span> <span class="n">request</span><span class="p">,</span> <span class="n">iq</span><span class="p">,</span> <span class="n">errorCondition</span><span class="p">,</span> <span class="n">message</span> <span class="p">-&gt;</span> <span class="nf">println</span><span class="p">(</span><span class="s">"Oops! Error $errorCondition"</span><span class="p">)</span> <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Use the one that you prefer.</p>

<p>One more example: we will check list of features of our server:</p>

<div class="language-kotlin highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">val</span> <span class="py">discoveryModule</span> <span class="p">=</span> <span class="n">client</span><span class="p">.</span><span class="n">getModule</span><span class="p">&lt;</span><span class="nc">DiscoveryModule</span><span class="p">&gt;(</span><span class="nc">DiscoveryModule</span><span class="p">.</span><span class="nc">TYPE</span><span class="p">)</span><span class="o">!!</span>
<span class="n">discoveryModule</span><span class="p">.</span><span class="nf">info</span><span class="p">(</span><span class="s">"sampleserver.org"</span><span class="p">.</span><span class="nf">toJID</span><span class="p">()).</span><span class="nf">handle</span> <span class="p">{</span>
    <span class="nf">error</span> <span class="p">{</span> <span class="n">request</span><span class="p">,</span> <span class="n">iq</span><span class="p">,</span> <span class="n">errorCondition</span><span class="p">,</span> <span class="n">message</span> <span class="p">-&gt;</span> <span class="nf">println</span><span class="p">(</span><span class="s">"Oops! Error $errorCondition"</span><span class="p">)</span> <span class="p">}</span>
    <span class="nf">success</span> <span class="p">{</span> <span class="n">request</span><span class="p">,</span> <span class="n">iq</span><span class="p">,</span> <span class="n">result</span> <span class="p">-&gt;</span>
        <span class="nf">println</span><span class="p">(</span><span class="s">"Server JID: ${result!!.jid}"</span><span class="p">)</span>
        <span class="nf">println</span><span class="p">(</span><span class="s">"Features:"</span><span class="p">)</span>
        <span class="n">result</span><span class="o">!!</span><span class="p">.</span><span class="n">features</span><span class="p">.</span><span class="nf">forEach</span> <span class="p">{</span> <span class="nf">println</span><span class="p">(</span><span class="s">" - $it"</span><span class="p">)</span> <span class="p">}</span>
    <span class="p">}</span>
<span class="p">}.</span><span class="nf">send</span><span class="p">()</span>
</code></pre></div></div>

<h2 id="messages">Messages</h2>

<p>This chapter will be very hard, mostly because <code class="language-plaintext highlighter-rouge">MessageModule</code> isn’t finished yet.
We haven’t made a design decision yet - how this module should work. It is good for you though, because we can create message stanza from scratch! And it’s cool!</p>

<p>This is how message stanza look like:</p>

<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;message</span>
      <span class="na">from=</span><span class="s">'juliet@example.com/balcony'</span>
      <span class="na">id=</span><span class="s">'ktx72v49'</span>
      <span class="na">to=</span><span class="s">'romeo@example.net'</span><span class="nt">&gt;</span>
    <span class="nt">&lt;body&gt;</span>Art thou not Romeo, and a Montague?<span class="nt">&lt;/body&gt;</span>
<span class="nt">&lt;/message&gt;</span>
</code></pre></div></div>

<p>Let’s try to create this stanza in Kotlin and send it.</p>

<div class="language-kotlin highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="py">messageRequest</span> <span class="p">=</span> <span class="n">client</span><span class="p">.</span><span class="n">request</span><span class="p">.</span><span class="nf">message</span> <span class="p">{</span>
    <span class="n">to</span> <span class="p">=</span> <span class="s">"romeo@example.net"</span><span class="p">.</span><span class="nf">toJID</span><span class="p">()</span>
    <span class="n">body</span> <span class="p">=</span> <span class="s">"Art thou not Romeo, and a Montague?"</span>
<span class="p">}</span>
<span class="n">messageRequest</span><span class="p">.</span><span class="nf">send</span><span class="p">()</span>
</code></pre></div></div>

<p>The only thing currently implemented in <code class="language-plaintext highlighter-rouge">MessageModule</code> is <code class="language-plaintext highlighter-rouge">MessageReceivedEvent</code>, useful to handle all incoming message stanzas:</p>

<div class="language-kotlin highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">client</span><span class="p">.</span><span class="n">eventBus</span><span class="p">.</span><span class="n">register</span><span class="p">&lt;</span><span class="nc">MessageReceivedEvent</span><span class="p">&gt;(</span><span class="nc">MessageReceivedEvent</span><span class="p">.</span><span class="nc">TYPE</span><span class="p">)</span> <span class="p">{</span> <span class="n">event</span> <span class="p">-&gt;</span>
    <span class="nf">println</span><span class="p">(</span><span class="s">"Message from ${event.fromJID}: ${event.stanza.body}"</span><span class="p">)</span>
<span class="p">}</span>
</code></pre></div></div>

<h2 id="roster-and-presence">Roster and presence</h2>

<p>Ok, we can send a message to anybody, but most of the time we want to send them to our friends.
We need a list of our friends. Luckily such list is available out-of-box in XMPP protocol: it is called Roster.</p>

<p>It shouldn’t be a surprise, but to manage your roster you need <code class="language-plaintext highlighter-rouge">RosterModule</code>:</p>

<div class="language-kotlin highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="py">rosterModule</span> <span class="p">=</span> <span class="n">client</span><span class="p">.</span><span class="n">getModule</span><span class="p">&lt;</span><span class="nc">RosterModule</span><span class="p">&gt;(</span><span class="nc">RosterModule</span><span class="p">.</span><span class="nc">TYPE</span><span class="p">)</span><span class="o">!!</span>
</code></pre></div></div>

<p>We can add (or update, with the same method) roster items, remove and list them.</p>

<div class="language-kotlin highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">val</span> <span class="py">allRosterItems</span> <span class="p">=</span> <span class="n">rosterModule</span><span class="p">.</span><span class="n">store</span><span class="p">.</span><span class="nf">getAllItems</span><span class="p">()</span>
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">RosterItem</code> contains JabberID of the contact, list of groups being assigned to, status of subscription (if contact is allowed to see our presence or not, and if we are allowed to see it’s presence).</p>

<p>Presence is “status of contact”. You can see if your contacts are online, offline or maybe you shouldn’t send any message to someone because he has “Do Not Disturb” status.</p>

<p>As an example, we will list all contacts from the roster and their presence:</p>

<div class="language-kotlin highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">rosterModule</span><span class="p">.</span><span class="n">store</span><span class="p">.</span><span class="nf">getAllItems</span><span class="p">().</span><span class="nf">forEach</span> <span class="p">{</span> <span class="n">rosterItem</span> <span class="p">-&gt;</span>
    <span class="kd">val</span> <span class="py">presenceStanza</span> <span class="p">=</span> <span class="n">presenceModule</span><span class="p">.</span><span class="nf">getBestPresenceOf</span><span class="p">(</span><span class="n">rosterItem</span><span class="p">.</span><span class="n">jid</span><span class="p">)</span>
    <span class="nf">println</span><span class="p">(</span><span class="s">"${rosterItem.name} &lt;${rosterItem.jid}&gt; : ${presenceStanza?.show ?: "</span><span class="nc">Offline</span><span class="s">"}"</span><span class="p">)</span>
<span class="p">}</span>
</code></pre></div></div>

<h2 id="thanks">Thanks…</h2>

<p>…for being here up to this point.
We hope you enjoyed reading about Halcyon library, and you liked it even though it is not finished yet.</p>

<p>Please share you thoughts and ideas at our group chat <a href="xmpp:tigase@muc.tigase.org?join">tigase@muc.tigase.org</a> or on <a href="https://github.com/tigase/halcyon">library GitHub page</a>.</p>]]></content><author><name>Tigase</name></author><category term="blog" /><category term="client" /><category term="library" /><category term="halcyon" /><category term="kotlin" /><category term="kotlin-multiplatform" /><category term="native" /><category term="js" /><category term="javascript" /><category term="android" /><summary type="html"><![CDATA[New XMPP library written in Kotlin with multiplatform goals.]]></summary></entry><entry><title type="html">Tigase XMPP Server meets Docker</title><link href="/blog/tigase-meets-docker/" rel="alternate" type="text/html" title="Tigase XMPP Server meets Docker" /><published>2020-08-25T00:00:00-07:00</published><updated>2020-08-25T00:00:00-07:00</updated><id>/blog/tigase-meets-docker</id><content type="html" xml:base="/blog/tigase-meets-docker/"><![CDATA[<p>Tigase XMPP Server is finally available as Docker image and you can grab it from DockerHub - setting the XMPP server 
was never easier.</p>

<p>Running Tigase XMPP Server was never easier - you can have a full-fledged XMPP server in a matter of minutes.</p>

<h1 id="benefits-of-tigase-xmpp-server-docker-image">Benefits of Tigase XMPP Server docker image</h1>

<p>Using containers offers various benefits - it helps bundle complete execution environment that’s consistent, isolates various services and orchestrates them with ease. This makes setting up new service a breeze. At the same time Docker is only a thin layer with very little performance overhead.
In Tigase’s case, even though normally only JVM is required, having single bundle with recommended version of the JVM and configured environment helps achieve the most compatible and stable setup.</p>

<h1 id="how-to-start">How to start</h1>

<p>If you haven’t already, <a href="https://docs.docker.com/engine/install/">install Docker engine</a> on your desired operating system. Once this is done, starting Tigase is just two commands away (for up-to-date list of tags check out <a href="https://hub.docker.com/r/tigase/tigase-xmpp-server">our DockerHub</a>, by default <code class="language-plaintext highlighter-rouge">latest</code> is used):</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ docker pull tigase/tigase-xmpp-server
$ docker run --name tigase-server -p 8080:8080 -p 5222:5222 tigase/tigase-xmpp-server
</code></pre></div></div>

<p>And after a short Tigase will start and you’ll be presented with option to setup the server by accessing http://localhost:8080 page. Once setup is completed, simply restart the container with <code class="language-plaintext highlighter-rouge">$ docker restart tigase-server</code> and connect your client.</p>

<p><img src="/assets/posts/docker-setup.png" alt="docker setup" /></p>

<h1 id="more-information">More information</h1>

<p>Of course above is the simplest deployment. There are many possibilities to adjust the container by mounting local volumes, exposing more ports or connecting to external database. It’s even possible to run local Tigase cluster! For details please check out <a href="https://github.com/tigase/tigase-xmpp-server-docker#configuration">Tigase in Docker guide</a></p>

<h1 id="java-in-docker---will-it-work">Java in Docker - will it work?</h1>

<p>Our images are based on Java 11, which already supports Docker without any issues.</p>]]></content><author><name>Tigase</name></author><category term="blog" /><category term="server" /><category term="distribution" /><category term="docker" /><category term="dockerhub" /><summary type="html"><![CDATA[Tigase XMPP Server is finally available as Docker image and you can grab it from DockerHub - setting the XMPP server was never easier]]></summary></entry></feed>