Written in 2019

This guide was written for Openfire 4.4 on Ubuntu 18.04 and is kept as it was published, with small corrections. The admin console in current Openfire releases is laid out a little differently, and the certbot install command has changed, but the idea is the same: get a certificate from Let's Encrypt, then import the private key and certificate into Openfire's identity store. For a fresh install on a current Ubuntu release, start with installing Openfire on Ubuntu.

Out of the box, Openfire generates a self-signed certificate. XMPP clients either warn about it or refuse to connect, and other servers won't federate with it. Replacing it with a free Let's Encrypt certificate fixes both.

Step 1: Generate the certificate with certbot

Point your XMPP domain at the server, open TCP port 80 for the Let's Encrypt HTTP-01 challenge, and request a certificate in standalone mode:

sudo certbot certonly --standalone -d yourdomain.com

The files land in /etc/letsencrypt/live/yourdomain.com/. You need two of them for the import: privkey.pem and cert.pem.

Step 2: Open the Openfire SSL identity store

In the Openfire admin console, open the certificate store management page:

http://yourdomain.com:9090/security-certificate-store-management.jsp
Openfire admin console certificate store management page listing the identity store and trust stores

Click Manage Store Contents under the Identity Store.

Openfire identity store contents page with the existing self-signed certificate and the import link

Click the link to import a new certificate.

Step 3: Paste the key and certificate

On the server, print the two files:

sudo cat /etc/letsencrypt/live/yourdomain.com/privkey.pem
sudo cat /etc/letsencrypt/live/yourdomain.com/cert.pem

Paste the contents of privkey.pem into Content of Private Key file and the contents of cert.pem into Content of Certificate file, then save.

Openfire import certificate form with fields for the private key content and the certificate content

Once the import succeeds, the Let's Encrypt certificate appears in the identity store. Remove the old self-signed certificate for the same domain so Openfire doesn't keep serving it.

Openfire identity store after the import, showing the new Let's Encrypt certificate alongside the self-signed one to delete

Step 4: Add the chain to the server trust store

For server-to-server connections, open the trust store used for connections from other servers:

http://yourdomain.com:9090/security-truststore.jsp?connectionType=SOCKET_S2S

Click Manage Store Contents, then the import form. Set the alias to Let's Encrypt, paste one certificate from fullchain.pem into Content of Certificate file, and save.

Openfire trust store import form with the alias set to Let's Encrypt and a certificate pasted in

Restart Openfire so it picks up the new identity certificate:

sudo systemctl restart openfire
Openfire certificate list showing the Let's Encrypt certificate installed and valid

About renewals

The one thing this 2019 method doesn't solve: Let's Encrypt certificates last 90 days. certbot renews the files in /etc/letsencrypt automatically, but Openfire keeps its own copy in its keystore, so the import has to happen again after each renewal. Put a reminder in your calendar at the very least, or script it with a certbot deploy hook. The same deploy-hook pattern is shown for another service in installing Coturn on Ubuntu.

For background on the protocol Openfire serves, see what XMPP is and how it works.

Frequently Asked Questions

Why does Openfire still show a self-signed certificate after importing Let's Encrypt?

Either the old self-signed entry is still in the identity store and being chosen first, or Openfire was not restarted after the import. Remove the self-signed certificate for your domain from the identity store, then restart Openfire.

Do I have to import the certificate again every 90 days?

With the manual method in this guide, yes. Let's Encrypt certificates expire after 90 days and certbot renews the files on disk, but Openfire keeps its own copy in its keystore. Script the import, or terminate TLS in front of Openfire, so renewals don't depend on someone remembering.

Should I use cert.pem or fullchain.pem?

This 2019 guide pasted cert.pem into the certificate field, which worked with the clients we tested then. If clients report an incomplete certificate chain, use fullchain.pem instead so the intermediate certificate is served too.

Which port must be open for certbot?

TCP 80, because certbot's standalone mode answers the HTTP-01 challenge itself. Nothing else can be listening on port 80 during the request, and the port can be closed again afterwards if you prefer.

Where does Openfire store its SSL certificate?

In its own keystore, not on disk beside the certbot files. Openfire's identity store holds the private key and certificate you paste into the admin console, and the trust store holds certificates from the other servers it federates with.