pre-configured MQTT server in Docker
Find a file
2026-06-22 22:33:57 -04:00
certs commit 2026-06-22 15:57:25 -04:00
config commit 2026-06-22 22:24:56 -04:00
.gitignore commit 2026-06-22 16:15:39 -04:00
add-user.sh commit 2026-06-22 15:57:25 -04:00
certbot.sh commit 2026-06-22 22:33:57 -04:00
docker-compose.yml commit 2026-06-22 15:57:25 -04:00
fix-perms.sh commit 2026-06-22 16:21:23 -04:00
LICENSE Initial commit 2026-06-22 19:38:10 +00:00
README.md commit 2026-06-22 22:33:57 -04:00

mqtt-docker

Template for running an MQTT broker with TLS in Docker using eclipse-mosquitto:2.

This repository provides a small, opinionated Mosquitto setup for MQTTS:

  • docker-compose.yml runs the broker on port 8883
  • config/mosquitto.conf enables persistence, disables anonymous access, and points Mosquitto at your TLS certs and password file
  • add-user.sh creates or updates Mosquitto users
  • certbot.sh can issue or renew Lets Encrypt certificates and export them into ./certs

Use

  1. Clone this repo and edit config/mosquitto.conf to match your domain name.

  2. Put your TLS files in ./certs using the naming Mosquitto expects:

    • ./certs/DOMAINHERE.crt
    • ./certs/DOMAINHERE.key

    Replace DOMAINHERE with your real hostname.

    If you do not have a certificate, see below.

  3. Start the broker:

    docker compose up -d
    
  4. Add an MQTT user:

    ./add-user.sh
    

    The script creates config/passwords if needed and updates the Mosquitto password file.

  5. Connect clients over TLS to port 8883 using your broker hostname, username, and password.

Getting certificates

Use certbot.sh to obtain or renew Lets Encrypt certificates. The script stops the container while Certbot runs, then exports the resulting certs into ./certs.

Issue or renew a single domain:

./certbot.sh example.com

Use Cloudflare DNS for a regular or wildcard cert:

./certbot.sh DNS
./certbot.sh DNS your-domain.example
./certbot.sh DNS mqtt.your-domain.example

Pass Cloudflare credentials either as CLI arguments in $2 and $3, or via environment variables:

./certbot.sh DNS your-cloudflare-api-token
./certbot.sh DNS your-cloudflare-api-token your-domain.example
./certbot.sh DNS your-cloudflare-api-token mqtt.your-domain.example

./certbot.sh DNS your-cloudflare-email@example.com your-cloudflare-api-key
./certbot.sh DNS your-cloudflare-email@example.com your-cloudflare-api-key your-domain.example
./certbot.sh DNS your-cloudflare-email@example.com your-cloudflare-api-key mqtt.your-domain.example

Or set one of these environment variable combinations:

CERTBOT_DNS_CLOUDFLARE_API_TOKEN=... ./certbot.sh DNS
CERTBOT_DNS_CLOUDFLARE_API_TOKEN=... ./certbot.sh DNS your-domain.example
CERTBOT_DNS_CLOUDFLARE_API_TOKEN=... ./certbot.sh DNS mqtt.your-domain.example

CERTBOT_DNS_CLOUDFLARE_EMAIL=... CERTBOT_DNS_CLOUDFLARE_API_KEY=... ./certbot.sh DNS
CERTBOT_DNS_CLOUDFLARE_EMAIL=... CERTBOT_DNS_CLOUDFLARE_API_KEY=... ./certbot.sh DNS your-domain.example
CERTBOT_DNS_CLOUDFLARE_EMAIL=... CERTBOT_DNS_CLOUDFLARE_API_KEY=... ./certbot.sh DNS mqtt.your-domain.example

DNS mode behavior:

  • No trailing target: renew existing certificates using the Cloudflare DNS plugin.
  • Trailing base domain like example.com: issue a wildcard certificate for *.example.com plus example.com.
  • Trailing specific hostname like mqtt.example.com: issue or renew that single hostname.

Renew all existing certificates:

./certbot.sh

Optional environment variables:

  • CERTBOT_EMAIL=you@example.com
  • CERTBOT_STAGING=1
  • CERTBOT_VENV=/opt/certbot-venv
  • PROJECT_DIR=/path/to/compose/dir
  • CERTBOT_DNS_CLOUDFLARE_API_TOKEN=...
  • CERTBOT_DNS_CLOUDFLARE_EMAIL=...
  • CERTBOT_DNS_CLOUDFLARE_API_KEY=...
  • CERTBOT_DNS_CREDENTIALS_FILE=/path/to/cloudflare.ini
  • CERTBOT_DNS_PROPAGATION_SECONDS=60
  • CERTBOT_DOMAIN=example.com

Notes

  • config/ holds broker configuration and credentials.
  • data/ stores Mosquitto persistence data.
  • certs/ is mounted read-only into the container.
  • When Cloudflare credentials are provided directly, the script writes them to /etc/letsencrypt/cloudflare.ini so renewals keep working.