Skip to content

TLS Configuration

Secure RabbitMQ connections with TLS encryption and optional client certificates.

CertificatePurpose
CA CertificateRoot of trust
Server CertificateRabbitMQ server identity
Client CertificateOptional client authentication
Terminal window
# Create CA directory
mkdir -p /etc/rabbitmq/ssl
cd /etc/rabbitmq/ssl
# Generate CA key
openssl genrsa -out ca.key 4096
# Generate CA certificate
openssl req -x509 -new -nodes \
-key ca.key \
-sha256 -days 3650 \
-out ca.crt \
-subj "/CN=Mantis RabbitMQ CA/O=Mantis"
Terminal window
# Generate server key
openssl genrsa -out server.key 2048
# Create certificate signing request
openssl req -new \
-key server.key \
-out server.csr \
-subj "/CN=rabbitmq.example.com/O=Mantis"
# Create SAN extension file
cat > server_san.ext << EOF
subjectAltName = @alt_names
[alt_names]
DNS.1 = rabbitmq.example.com
DNS.2 = localhost
IP.1 = 127.0.0.1
EOF
# Sign with CA
openssl x509 -req \
-in server.csr \
-CA ca.crt \
-CAkey ca.key \
-CAcreateserial \
-out server.crt \
-days 365 \
-sha256 \
-extfile server_san.ext
Terminal window
# Generate client key
openssl genrsa -out client.key 2048
# Create CSR
openssl req -new \
-key client.key \
-out client.csr \
-subj "/CN=mantis-client/O=Mantis"
# Sign with CA
openssl x509 -req \
-in client.csr \
-CA ca.crt \
-CAkey ca.key \
-CAcreateserial \
-out client.crt \
-days 365 \
-sha256
Terminal window
# Secure the keys
chmod 600 /etc/rabbitmq/ssl/*.key
chmod 644 /etc/rabbitmq/ssl/*.crt
chown -R rabbitmq:rabbitmq /etc/rabbitmq/ssl
/etc/rabbitmq/rabbitmq.conf
# Disable plain TCP listener (recommended for production)
# listeners.tcp = none
# Enable TLS listener
listeners.ssl.default = 5671
# Certificate configuration
ssl_options.cacertfile = /etc/rabbitmq/ssl/ca.crt
ssl_options.certfile = /etc/rabbitmq/ssl/server.crt
ssl_options.keyfile = /etc/rabbitmq/ssl/server.key
# TLS version (require TLS 1.2+)
ssl_options.versions.1 = tlsv1.2
ssl_options.versions.2 = tlsv1.3
# Cipher suites
ssl_options.ciphers.1 = TLS_AES_256_GCM_SHA384
ssl_options.ciphers.2 = TLS_AES_128_GCM_SHA256
ssl_options.ciphers.3 = ECDHE-RSA-AES256-GCM-SHA384
ssl_options.ciphers.4 = ECDHE-RSA-AES128-GCM-SHA256
# Honor server cipher preference
ssl_options.honor_cipher_order = true
ssl_options.honor_ecc_order = true
/etc/rabbitmq/rabbitmq.conf
# Require client certificates
ssl_options.verify = verify_peer
ssl_options.fail_if_no_peer_cert = true
# Depth of certificate chain verification
ssl_options.depth = 2

For migration or internal/external separation:

/etc/rabbitmq/rabbitmq.conf
# TCP on localhost only
listeners.tcp.local = 127.0.0.1:5672
# TLS on all interfaces
listeners.ssl.default = 5671
/etc/rabbitmq/rabbitmq.conf
# Disable HTTP
management.tcp.port = 0
# Enable HTTPS
management.ssl.port = 15671
management.ssl.cacertfile = /etc/rabbitmq/ssl/ca.crt
management.ssl.certfile = /etc/rabbitmq/ssl/server.crt
management.ssl.keyfile = /etc/rabbitmq/ssl/server.key
thorax.toml
[queue]
enabled = true
host = "rabbitmq.example.com"
port = 5671
username = "mantis"
password = "password"
ca_cert_path = "/etc/mantis/certs/rabbitmq-ca.crt"
prefetch_count = 10
thorax.toml
[queue]
enabled = true
host = "rabbitmq.example.com"
port = 5671
username = "mantis"
password = "password"
ca_cert_path = "/etc/mantis/certs/ca.crt"
client_cert_path = "/etc/mantis/certs/client.crt"
client_key_path = "/etc/mantis/certs/client.key"
Terminal window
THORAX__QUEUE__HOST="rabbitmq.example.com"
THORAX__QUEUE__PORT=5671
THORAX__QUEUE__USERNAME="mantis"
THORAX__QUEUE__CA_CERT_PATH="/etc/mantis/certs/ca.crt"

Mandible publishes commands to RabbitMQ and uses the same [queue] settings block with the MANDIBLE__ env var prefix.

mandible.toml
[queue]
enabled = true
host = "rabbitmq.example.com"
port = 5671
username = "mantis"
password = "password"
ca_cert_path = "/etc/mantis/certs/rabbitmq-ca.crt"
mandible.toml
[queue]
enabled = true
host = "rabbitmq.example.com"
port = 5671
username = "mantis"
password = "password"
ca_cert_path = "/etc/mantis/certs/ca.crt"
client_cert_path = "/etc/mantis/certs/client.crt"
client_key_path = "/etc/mantis/certs/client.key"
Terminal window
MANDIBLE__QUEUE__HOST="rabbitmq.example.com"
MANDIBLE__QUEUE__PORT=5671
MANDIBLE__QUEUE__USERNAME="mantis"
MANDIBLE__QUEUE__CA_CERT_PATH="/etc/mantis/certs/ca.crt"
services:
rabbitmq:
image: rabbitmq:3.13-management-alpine
hostname: rabbitmq
volumes:
- ./ssl/ca.crt:/etc/rabbitmq/ssl/ca.crt:ro
- ./ssl/server.crt:/etc/rabbitmq/ssl/server.crt:ro
- ./ssl/server.key:/etc/rabbitmq/ssl/server.key:ro
- ./rabbitmq.conf:/etc/rabbitmq/rabbitmq.conf:ro
ports:
- '5671:5671' # AMQPS
- '15671:15671' # Management HTTPS
apiVersion: v1
kind: Secret
metadata:
name: rabbitmq-tls
type: Opaque
data:
ca.crt: <base64-encoded-ca>
server.crt: <base64-encoded-cert>
server.key: <base64-encoded-key>
Terminal window
# Using OpenSSL
openssl s_client -connect rabbitmq.example.com:5671 \
-CAfile /etc/mantis/certs/ca.crt \
-showcerts
# Check certificate
openssl s_client -connect rabbitmq.example.com:5671 \
-CAfile /etc/mantis/certs/ca.crt \
</dev/null 2>/dev/null | openssl x509 -text -noout
Terminal window
# Using amqp-tools
amqp-declare-queue \
--url="amqps://mantis:password@rabbitmq.example.com:5671" \
--cacert=/etc/mantis/certs/ca.crt \
--queue=test
# Using Python
python3 -c "
import ssl
import pika
context = ssl.create_default_context(cafile='/etc/mantis/certs/ca.crt')
params = pika.ConnectionParameters(
host='rabbitmq.example.com',
port=5671,
credentials=pika.PlainCredentials('mantis', 'password'),
ssl_options=pika.SSLOptions(context)
)
connection = pika.BlockingConnection(params)
print('Connected successfully')
connection.close()
"
Terminal window
# List TLS listeners
sudo rabbitmqctl eval 'rabbit_networking:active_listeners().'
# Check connection TLS info
sudo rabbitmqctl list_connections name ssl ssl_protocol ssl_cipher
/opt/mantis/scripts/renew-rabbitmq-certs.sh
#!/bin/bash
SSL_DIR="/etc/rabbitmq/ssl"
DAYS_BEFORE_EXPIRY=30
# Check if certificate needs renewal
EXPIRY=$(openssl x509 -enddate -noout -in $SSL_DIR/server.crt | cut -d= -f2)
EXPIRY_EPOCH=$(date -d "$EXPIRY" +%s)
NOW_EPOCH=$(date +%s)
DAYS_LEFT=$(( ($EXPIRY_EPOCH - $NOW_EPOCH) / 86400 ))
if [ $DAYS_LEFT -lt $DAYS_BEFORE_EXPIRY ]; then
echo "Certificate expires in $DAYS_LEFT days, renewing..."
# Generate new certificate
openssl req -new -key $SSL_DIR/server.key -out $SSL_DIR/server.csr \
-subj "/CN=rabbitmq.example.com/O=Mantis"
openssl x509 -req -in $SSL_DIR/server.csr \
-CA $SSL_DIR/ca.crt -CAkey $SSL_DIR/ca.key \
-CAcreateserial -out $SSL_DIR/server.crt \
-days 365 -sha256 -extfile $SSL_DIR/server_san.ext
# Reload RabbitMQ
sudo systemctl reload rabbitmq-server
echo "Certificate renewed successfully"
else
echo "Certificate valid for $DAYS_LEFT more days"
fi
Terminal window
# Weekly check
0 0 * * 0 /opt/mantis/scripts/renew-rabbitmq-certs.sh >> /var/log/rabbitmq/cert-renewal.log 2>&1
Error: TLS handshake failed

Causes:

  1. Certificate hostname mismatch
  2. Expired certificate
  3. CA certificate not trusted

Solutions:

  1. Verify SAN includes hostname: openssl x509 -in server.crt -text | grep DNS
  2. Check expiry: openssl x509 -in server.crt -enddate -noout
  3. Verify CA is correct
Error: certificate verify failed

Solutions:

  1. Ensure CA certificate is correct
  2. Check certificate chain is complete
  3. Verify verify_peer settings match on both sides
Error: connection reset by peer

Causes:

  1. TLS version mismatch
  2. Cipher suite incompatibility

Solutions:

  1. Check TLS versions match
  2. Verify cipher suites are compatible