Decorative site banner
Project icon

com.io7m.adelaide

  • About
  • Releases
  • Manual
  • Sources
  • License
  • Issues
Maven Central Version Maven Snapshot Code Coverage

adelaide


Better ActiveMQ Artemis OCI images.

Motivation


The existing Artemis OCI images have a number of problems that are addressed by the adelaide images.

  • The original images expect users to generate configuration files and then use them in the broker instances. This makes the container the "owner" of the configuration files instead of the files being a read-only input to the container, and makes it difficult to keep them in version control. Additionally, the images seem to be designed under the assumption that a user might want to run more than one broker in a container instance. Nobody sensible wants to do this. The adelaide images expose a single /data volume for the single broker instance supported by the container, and expose a single /data/etc volume to allow for configuration files to be read-only mounted in the container, and managed externally.

  • The images expect to be run under Docker, and therefore do the usual idiotic "run as a separate UID inside the container" dance. This is a fundamental design flaw of Docker and is one of many reasons to exclusively use podman instead. The adelaide images do not do any manipulation of UIDs or GIDs; if you run the adelaide image as UID 0 on the host, Artemis will run as UID 0 inside the container. Simply run podman as a non-root user on the host, and everything inside the container is guaranteed to run without privileges of any kind. The adelaide images do not support Docker; this is a feature and not a bug.

  • The adelaide images are free of any platform-specific complexity. Noone sensible is hosting message broker containers on any platform other than Linux.

  • The adelaide images are designed to be run with an entirely read-only filesystem (aside from the read/write mounted broker instance directory). This is intended to allow for greater reliability and security.

Features


  • Runs rootless with a read-only root directory!
  • Version control your broker configuration files!
  • Easy TLS reloading for ACME.
  • ISC license.

Usage


Run podman as an unprivileged user, with an invocation similar to:

podman run \ --read-only \ --volume '/path/to/host/tls:/tls:ro,z' \ --volume '/path/to/broker/data:/data:Z,rw' \ --volume '/path/to/broker/etc:/data/etc:Z,ro' \ --publish '...:61616:61616/tcp' \ quay.io/io7mcom/adelaide:${VERSION}

Naturally, the exact directories you mount, and the exact TCP ports you publish is dependent on your broker configuration.

Use the following volume mounts:

MountDescription
/dataPersistent broker data (the "broker instance")
/data/etcBroker configuration files (such as broker.xml)
/tlsA directory containing keystores.

The /data mount contains the persistent state of the one-and-only broker instance used by the container.

The /data/etc mount should be mounted read-only and should contain your version-controlled broker configuration files (such as broker.xml).

The /tls mount should contain keystores and truststores.

For extra security, run podman run with the --read-only option; the images are designed such that no part of the filesystem except for /data is required to be writable.

TLS Reloading


The image provides a /broker-tls-reload.sh script that can be executed inside the container to instruct Artemis to reload TLS certificates. We'll assume that the broker container is being run under the _artemis user account on the host throughout this example.

# /broker-tls-reload.sh usage: user password broker-name acceptor-name

We'll start by assuming that we have some client on the host that knows how to write PEM-formatted certificates into some directory (any ACME client can do this). We'll then periodically (hourly is sufficient) convert those PEM-formatted certificates to a PKCS12 formatted keystore and write the keystore to a path that is visible to the broker running inside the container. We'll then tell the broker to reload its own keystore. The steps are as follows:

  1. Configure your broker to read a keystore from /tls/brokerKeystore.pkcs12. For example, in the broker.xml:

<acceptor name="artemis"> tcp://0.0.0.0:60000?protocols=AMQP;sslEnabled=true;keyStorePath=/tls/brokerKeystore.p12;keyStorePassword=changeit;trustStorePath=/opt/java/openjdk/lib/security/cacerts;trustStorePassword=changeit </acceptor>

  1. Write a script to generate /tls/brokerKeystore.p12 from outside of the container. For the sake of example, we'll refer to this script as /usr/local/bin/regenerate-keystore.sh on the host. For example, if an ACME client is placing certificates into the host directory /etc/certificates/example.com, and the directory /containers/messaging01/tls is mounted at /tls in the container, then it is straightforward to write a script to produce a PKCS12 keystore:

#!/bin/sh -ex CERTIFICATE_BASE="/etc/certificates/example.com" OUTPUT="/containers/messaging01/tls" openssl pkcs12 \ -export \ -out "${OUTPUT}/brokerKeystore.p12.tmp" \ -in "${CERTIFICATE_BASE}/full_chain.pem" \ -inkey "${CERTIFICATE_BASE}/private.key" \ -passout "pass:changeit" chown _artemis:_artemis "${OUTPUT}/brokerKeystore.p12.tmp" mv "${OUTPUT}/brokerKeystore.p12.tmp" "${OUTPUT}/brokerKeystore.p12"

  1. Set up a service to periodically call the script to generate the keystore, and then call /broker-tls-reload.sh inside the container to reload certificates. In this example, we assume that the container is called messaging01, and it exposes a broker called Messaging01 with an acceptor called artemis. It also has an admin user called grouch with a password some-very-long-password-here. Naturally, all of these values will likely be different for your particular broker installation.

[Unit] Description=Messaging01 TLS Service [Service] Type=oneshot User=_artemis Group=_artemis ExecStart=+/bin/sh /usr/local/bin/regenerate-keystore.sh ExecStart=/usr/bin/podman \ exec \ -i \ -t \ messaging01 \ /broker-tls-reload.sh \ grouch \ some-very-long-password-here \ Messaging01 \ artemis [Install] WantedBy=multi-user.target

[Unit] Description=Messaging01 TLS timer [Timer] OnCalendar=*-*-* *:00/59:00 Persistent=true [Install] WantedBy=timers.target

Releases & Development Snapshots


Releases


You can subscribe to the atom feed to be notified of project releases.

No formal releases have been made yet.

Development Snapshots


At the time of writing, the current unstable development version of the package is 1.0.0.

Development snapshots may be available in the Central Portal Snapshots repository. Snapshots are published to this repository every time the project is built by the project's continuous integration system, but snapshots do expire after around ninety days and so may or may not be available depending on when a build of the package was last triggered.

Manual


This project does not have any user manuals or other documentation beyond what might be present on the page above.

Sources


This project uses Git to manage source code.

Repository: https://www.github.com/io7m-com/adelaide

$ git clone --recursive https://www.github.com/io7m-com/adelaide

Issues


This project uses GitHub Issues to track issues.

License


Copyright © 2025 Mark Raynsford <code@io7m.com> https://www.io7m.com Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies. THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

Last Updated 2025-08-10T18:34:29Z