12 changed files with 420 additions and 0 deletions
@ -0,0 +1,26 @@ |
|||||
|
##
|
||||
|
## Makefile for Mosquitto quadlet
|
||||
|
##
|
||||
|
|
||||
|
DEPENDENCIES = traefik |
||||
|
|
||||
|
# Mosquitto runs as UID 10033 (mosquitto) / GID 10000 (itix-svc) on the host
|
||||
|
PROJECT_UID = 10033 |
||||
|
PROJECT_GID = 10000 |
||||
|
|
||||
|
# The conf.d directory must exist even when empty: mosquitto's include_dir fails if the
|
||||
|
# directory is missing. Ship it as a packaged (persistent) directory.
|
||||
|
TARGET_FILES += $(TARGET_CHROOT)/etc/quadlets/mosquitto/conf.d |
||||
|
|
||||
|
# Include common Makefile
|
||||
|
include ../../scripts/common.mk |
||||
|
|
||||
|
$(TARGET_CHROOT)/etc/quadlets/mosquitto/conf.d: |
||||
|
install -d -m 0755 -o $(PROJECT_UID) -g $(PROJECT_GID) -D $@ |
||||
|
|
||||
|
# The example password and ACL files stand in for the operator-provided secrets. Install
|
||||
|
# them with the same 0640 mode and 10033:10000 ownership that the operator must use,
|
||||
|
# overriding the default 0644 config-install rule for these two files.
|
||||
|
TARGET_MOSQUITTO_SECRET_EXAMPLES = $(patsubst config/examples/%, $(TARGET_CHROOT)/etc/quadlets/mosquitto/%, $(wildcard config/examples/passwd config/examples/acl)) |
||||
|
$(TARGET_MOSQUITTO_SECRET_EXAMPLES): $(TARGET_CHROOT)/etc/quadlets/mosquitto/%: config/examples/% $(TARGET_CHROOT)/etc/quadlets/mosquitto |
||||
|
install -m 0640 -o $(PROJECT_UID) -g $(PROJECT_GID) $< $@ |
||||
@ -0,0 +1,187 @@ |
|||||
|
# Podman Quadlet: Mosquitto |
||||
|
|
||||
|
## Overview |
||||
|
|
||||
|
[Eclipse Mosquitto](https://mosquitto.org/) is a lightweight MQTT broker. This cookbook |
||||
|
runs it as a Podman Quadlet to serve as the MQTT backbone of a home-automation stack |
||||
|
(Home Assistant, `zigbee2mqtt`, ESPHome, ...). |
||||
|
|
||||
|
This cookbook: |
||||
|
|
||||
|
- Runs Mosquitto as a rootless container (UID 10033) with minimal privileges. |
||||
|
- Binds a plain-MQTT listener on **loopback only** (`127.0.0.1:1883`). Nothing listens on |
||||
|
the LAN by default. |
||||
|
- Terminates TLS **at Traefik** (port 443, demultiplexed by SNI), not inside the broker — |
||||
|
it depends on the `traefik` cookbook. |
||||
|
- Refuses anonymous access; authentication and topic authorization come from operator-provided |
||||
|
files. |
||||
|
- Stores retained messages and client sessions on the virtiofs precious-data mount |
||||
|
(`/var/lib/virtiofs/data/mosquitto/`), so the host's ZFS snapshots and backups pick them up. |
||||
|
- Logs everything to stdout, so `journalctl` is the single place to look. |
||||
|
- Supports automatic container image updates via Podman auto-update. |
||||
|
|
||||
|
The image is `docker.io/library/eclipse-mosquitto:2`, a multi-architecture manifest |
||||
|
(amd64 + arm64, verified 2026-09-19, version 2.1.2), as required by the aarch64 target. |
||||
|
|
||||
|
## Prerequisites |
||||
|
|
||||
|
- The `traefik` cookbook must be installed and running (installed automatically as a |
||||
|
dependency). |
||||
|
- The virtiofs data mount `/var/lib/virtiofs/data` must be present (provided by the |
||||
|
`fcos-with-virtiofs` template / the `base` cookbook). |
||||
|
- The operator must provide a password file and an ACL file (see below). Until the |
||||
|
password file exists, the broker is intentionally **not** started (the units carry a |
||||
|
`ConditionPathExists=/etc/quadlets/mosquitto/passwd` guard). |
||||
|
|
||||
|
## Files the operator must provide |
||||
|
|
||||
|
Both files are provided by the operator (e.g. an Ansible role from a vault) and are **not** |
||||
|
part of the package. Working examples ship under `config/examples/` for development only. |
||||
|
|
||||
|
| Path | Mode | Owner | Purpose | |
||||
|
|-------------------------------------|------|--------------|-------------------------------------------| |
||||
|
| `/etc/quadlets/mosquitto/passwd` | 0640 | `10033:10000`| MQTT username/password database | |
||||
|
| `/etc/quadlets/mosquitto/acl` | 0640 | `10033:10000`| Per-user topic authorization | |
||||
|
|
||||
|
Site-specific Traefik routing (real SNI host name + certificate resolver) is injected |
||||
|
downstream as an overlay into `/etc/quadlets/traefik/conf.d/` — see |
||||
|
[TLS at Traefik](#tls-at-traefik) below. No site value is baked into this cookbook. |
||||
|
|
||||
|
### Generating a password entry |
||||
|
|
||||
|
Use `mosquitto_passwd` (available inside the broker image, or from the `mosquitto-clients` |
||||
|
package): |
||||
|
|
||||
|
```sh |
||||
|
# Create/replace the file and add the first user: |
||||
|
mosquitto_passwd -c -b /etc/quadlets/mosquitto/passwd homeassistant 'S3cr3t!' |
||||
|
# Add more users (omit -c so the file is not truncated): |
||||
|
mosquitto_passwd -b /etc/quadlets/mosquitto/passwd zigbee2mqtt 'An0th3r!' |
||||
|
``` |
||||
|
|
||||
|
Then make sure ownership and mode are correct: |
||||
|
|
||||
|
```sh |
||||
|
chown 10033:10000 /etc/quadlets/mosquitto/passwd |
||||
|
chmod 0640 /etc/quadlets/mosquitto/passwd |
||||
|
``` |
||||
|
|
||||
|
The ACL file uses Mosquitto's ACL syntax; see `config/examples/acl` for a starting point. |
||||
|
Because `acl_file` is set and anonymous access is refused, access is **default-deny**: an |
||||
|
authenticated user can only touch the topics granted to it. |
||||
|
|
||||
|
## TLS at Traefik |
||||
|
|
||||
|
The broker speaks **plain MQTT** on loopback. Traefik terminates TLS on port 443 and |
||||
|
demultiplexes connections by SNI, forwarding the plaintext stream to `127.0.0.1:1883`. This |
||||
|
is expressed as a Traefik **TCP** router (not an HTTP one), shipped as a hook fragment in |
||||
|
`other/traefik/mosquitto.yaml` and installed to `/etc/quadlets/traefik/conf.d/mosquitto.yaml` |
||||
|
during development. |
||||
|
|
||||
|
What this implies for clients: |
||||
|
|
||||
|
- All clients are **remote** and connect over **TLS on port 443** using the broker's SNI host |
||||
|
name (e.g. `mqtt.itix.fr` in production, `mqtt` in the shipped example), *not* to port 1883. |
||||
|
Example round trip through Traefik: |
||||
|
|
||||
|
```sh |
||||
|
mosquitto_sub --cafile /path/to/ca.crt -h mqtt -p 443 -u homeassistant -P '…' -t 'test/#' & |
||||
|
mosquitto_pub --cafile /path/to/ca.crt -h mqtt -p 443 -u homeassistant -P '…' -t 'test/x' -m hello |
||||
|
``` |
||||
|
|
||||
|
- **Credentials travel in clear text between Traefik and the broker** over the loopback |
||||
|
interface (Traefik has already terminated TLS). This is acceptable because loopback traffic |
||||
|
never leaves the host, but it is stated here so it is not a surprise. |
||||
|
|
||||
|
- The shipped fragment uses a bare `tls: {}`, which makes Traefik serve its own self-signed |
||||
|
certificate — good enough to test the path end-to-end. In production the operator overlays a |
||||
|
fragment with the real SNI host name and `certResolver: le` (the certificate resolver is a |
||||
|
site value and is kept commented out in the package). |
||||
|
|
||||
|
A TCP router whose `HostSNI` is not `` `*` `` **requires** a `tls` section, a TCP service uses |
||||
|
`address:` (never `url:`), and this router coexists on the `https` entry point with the HTTP |
||||
|
routers of the other cookbooks, which match `HostSNI(`*`)` implicitly. |
||||
|
|
||||
|
### Making the broker listen on the LAN (optional) |
||||
|
|
||||
|
If an operator nevertheless wants the broker to accept connections directly on the LAN, they |
||||
|
can drop a fragment such as `listener 8883 0.0.0.0` (plus its own TLS/authentication settings) |
||||
|
into `/etc/quadlets/mosquitto/conf.d/`. This cookbook ships no LAN listener and no firewall |
||||
|
rules. |
||||
|
|
||||
|
## Ports |
||||
|
|
||||
|
| Port | Bind | Purpose | |
||||
|
|------|-------------|-----------------------------------------------------| |
||||
|
| 1883 | `127.0.0.1` | Plain MQTT listener (loopback only) | |
||||
|
| 443 | Traefik | TLS-terminated MQTT ingress (SNI-routed by Traefik) | |
||||
|
|
||||
|
Port 1883 is above 1024, so the non-root container binds it without any capability. |
||||
|
|
||||
|
## UID and GID |
||||
|
|
||||
|
- User: `mosquitto`, UID **10033** |
||||
|
- Group: `itix-svc`, GID **10000** |
||||
|
|
||||
|
## Health check |
||||
|
|
||||
|
The health probe is a bare TCP connect to the listener (`nc -z 127.0.0.1 1883`). It is |
||||
|
preferred over a credentialed `mosquitto_sub` on `$SYS/#` because it needs **no secret** — |
||||
|
the operator's password file may legitimately not be in place yet, and the probe must not |
||||
|
depend on it. As a side effect, each probe produces a benign `New connection` / |
||||
|
`disconnected: connection closed by client` log pair in the journal; raise `HealthInterval` |
||||
|
or set `connection_messages false` in a `conf.d` fragment if that noise is unwanted. |
||||
|
|
||||
|
## Deviations from the repository conventions |
||||
|
|
||||
|
- **No TLS inside the container and no `lego` dependency.** TLS is Traefik's job, mirroring |
||||
|
the production montage (Traefik `HostSNI` + `certResolver: le` in front of port 1883). The |
||||
|
Traefik hook is a **TCP** router rather than the usual HTTP one. |
||||
|
- **The whole `/etc/quadlets/mosquitto` directory is mounted read-only** into the container |
||||
|
(at the same path) rather than mounting individual files, so that `mosquitto.conf`, the |
||||
|
`conf.d/` fragments and the operator-provided `passwd`/`acl` all appear without enumerating |
||||
|
them, and host and container paths stay identical. |
||||
|
- **Health check is an unauthenticated TCP connect** (see above), not the credentialed |
||||
|
`$SYS/#` subscription some deployments use. |
||||
|
- **The `conf.d/` directory is packaged as an empty directory** because Mosquitto's |
||||
|
`include_dir` fails if the directory is missing (verified against 2.1.2; it is also |
||||
|
non-recursive and only reads `*.conf`). |
||||
|
|
||||
|
## Usage |
||||
|
|
||||
|
In a separate terminal, follow the logs. |
||||
|
|
||||
|
```sh |
||||
|
sudo make tail-logs |
||||
|
``` |
||||
|
|
||||
|
Install the Podman Quadlets and start Mosquitto (pulls in `traefik`). |
||||
|
|
||||
|
```sh |
||||
|
sudo make clean install |
||||
|
``` |
||||
|
|
||||
|
Verify the broker is listening on loopback (and nowhere else): |
||||
|
|
||||
|
```sh |
||||
|
ss -ltnp | grep 1883 |
||||
|
``` |
||||
|
|
||||
|
Publish/subscribe round trip with a password (using the shipped development credentials): |
||||
|
|
||||
|
```sh |
||||
|
mosquitto_sub -h 127.0.0.1 -p 1883 -u homeassistant -P homeassistant -t 'test/#' & |
||||
|
mosquitto_pub -h 127.0.0.1 -p 1883 -u homeassistant -P homeassistant -t 'test/x' -m hello |
||||
|
``` |
||||
|
|
||||
|
Anonymous access must be refused: |
||||
|
|
||||
|
```sh |
||||
|
mosquitto_pub -h 127.0.0.1 -p 1883 -t 'test/x' -m nope # -> Connection Refused: not authorised. |
||||
|
``` |
||||
|
|
||||
|
Finally, remove the quadlets, their configuration and their data. |
||||
|
|
||||
|
```sh |
||||
|
sudo make I_KNOW_WHAT_I_AM_DOING=yes uninstall clean |
||||
|
``` |
||||
@ -0,0 +1,18 @@ |
|||||
|
# Example Mosquitto ACL file (DEVELOPMENT ONLY - do NOT use in production). |
||||
|
# |
||||
|
# In production this file is provided by the operator at |
||||
|
# /etc/quadlets/mosquitto/acl (mode 0640, owned by 10033:10000). |
||||
|
# |
||||
|
# With acl_file set and allow_anonymous false, access is default-deny: an |
||||
|
# authenticated user can only touch the topics granted to it here. Tighten these |
||||
|
# rules per client in production (e.g. restrict zigbee2mqtt to the zigbee2mqtt/# |
||||
|
# tree). The examples below grant each development user full access. |
||||
|
|
||||
|
user homeassistant |
||||
|
topic readwrite # |
||||
|
|
||||
|
user zigbee2mqtt |
||||
|
topic readwrite # |
||||
|
|
||||
|
user esphome |
||||
|
topic readwrite # |
||||
@ -0,0 +1,15 @@ |
|||||
|
# Example Mosquitto password file (DEVELOPMENT ONLY - do NOT use in production). |
||||
|
# |
||||
|
# In production this file is provided by the operator at |
||||
|
# /etc/quadlets/mosquitto/passwd (mode 0640, owned by 10033:10000). Generate an |
||||
|
# entry with: |
||||
|
# |
||||
|
# mosquitto_passwd -b /etc/quadlets/mosquitto/passwd <username> <password> |
||||
|
# |
||||
|
# The username:password pairs below are, respectively: |
||||
|
# homeassistant / homeassistant |
||||
|
# zigbee2mqtt / zigbee2mqtt |
||||
|
# esphome / esphome |
||||
|
homeassistant:$7$1000$0ca+E0ECJyUjNmtIarQIiUR0zIfkBvRuTRP/SmXyLvKIhi+YJEAeUTMfqJJWE/cpB/SqombhtS51GGXTUvm/JA==$lmvIk0V2EuBG9kzWtuIzaF58keiwX6hVCnMz/P5u2SEAtw2TneNi58IYf6YNubR88etNa26MQ9rOJVCI7VqOeA== |
||||
|
zigbee2mqtt:$7$1000$KFNPZOqPGZ5tdJuX1L2Nhckm1HiQYW4rUnyB6EcZcZdckMHJaTZmhBfO5KpB13wEdO+Muyff4j2c5/iBX/Hbmg==$XvtozXmh541JUhwvFeKfr/usnmoR3VDTxPz47oAvoLJjpZupNeRmPk9JsYsVOKy55eoO9qKzeleCH2h1y0+6kA== |
||||
|
esphome:$7$1000$DSDWpCqjOEWOdyQerw1yMeLAXiJAscic5GbTZ4KFrW6R1UuB+MxrRT26g1v0sQZrLXPMLc8ev/942o2yDQwGpw==$w8br+ek/wfYug0cw/43vklsnPypQVR6yhvc/WQThDK0+EvxwniJ73gQXCueL9D82wWMv26Bm9tBHpgik/RxvLQ== |
||||
@ -0,0 +1,34 @@ |
|||||
|
# Mosquitto broker configuration (packaged, treated as read-only). |
||||
|
# |
||||
|
# This file ships with the cookbook. Site-specific configuration and fragments |
||||
|
# contributed by dependent cookbooks go into the conf.d directory referenced by |
||||
|
# the include_dir directive at the end of this file. |
||||
|
|
||||
|
# Send every log line to stdout so journalctl is the single place to look. |
||||
|
# Do NOT configure log_dest file / do not mount /mosquitto/log. |
||||
|
log_dest stdout |
||||
|
|
||||
|
# Persist retained messages and client sessions to the precious data directory, |
||||
|
# which is virtiofs-backed and picked up by the host's ZFS snapshots and backups. |
||||
|
persistence true |
||||
|
persistence_location /var/lib/virtiofs/data/mosquitto/ |
||||
|
|
||||
|
# Default listener: plain MQTT, bound to loopback only. Nothing listens on the LAN. |
||||
|
# TLS is terminated by Traefik on :443 and demultiplexed by SNI (see the README and |
||||
|
# other/traefik/mosquitto.yaml); the broker itself never speaks TLS. |
||||
|
listener 1883 127.0.0.1 |
||||
|
|
||||
|
# Authentication: anonymous access is refused. The password file is provided by the |
||||
|
# operator (Ansible, from a vault) at the path below; a working example ships under |
||||
|
# config/examples/ for development only. |
||||
|
allow_anonymous false |
||||
|
password_file /etc/quadlets/mosquitto/passwd |
||||
|
|
||||
|
# Topic authorization, also operator-provided (example under config/examples/). |
||||
|
acl_file /etc/quadlets/mosquitto/acl |
||||
|
|
||||
|
# Site configuration and dependent-cookbook fragments are dropped here. |
||||
|
# Caveats of mosquitto's include_dir (verified against 2.1.2): it is NOT recursive, |
||||
|
# it only reads files matching *.conf, and it FAILS if the directory is missing. |
||||
|
# The directory is therefore created unconditionally (packaged as an empty directory). |
||||
|
include_dir /etc/quadlets/mosquitto/conf.d |
||||
@ -0,0 +1,17 @@ |
|||||
|
# Mosquitto configuration fragments
|
||||
|
# This hook lets a dependent cookbook drop a configuration fragment into the broker's
|
||||
|
# include_dir by placing a file named other/mosquitto/<name>.conf in its own directory.
|
||||
|
# It lands in /etc/quadlets/mosquitto/conf.d/<name>.conf and is loaded by mosquitto.
|
||||
|
|
||||
|
# Define the target files deployed to the target system when the hook is used by a
|
||||
|
# dependent cookbook.
|
||||
|
TARGET_MOSQUITTO_FILES = $(patsubst other/mosquitto/%.conf, $(TARGET_CHROOT)/etc/quadlets/mosquitto/conf.d/%.conf, $(wildcard other/mosquitto/*.conf)) |
||||
|
|
||||
|
# Those fragments are examples for the dependent cookbooks and thus are not part of the
|
||||
|
# final package.
|
||||
|
TARGET_EXAMPLE_FILES += $(TARGET_MOSQUITTO_FILES) |
||||
|
|
||||
|
# Define the installation rule for the target files. Owned by the broker user so it can
|
||||
|
# read them (they are mounted read-only into the container).
|
||||
|
$(TARGET_CHROOT)/etc/quadlets/mosquitto/conf.d/%.conf: other/mosquitto/%.conf |
||||
|
install -D -m 0644 -o 10033 -g 10000 $< $@ |
||||
@ -0,0 +1,57 @@ |
|||||
|
[Unit] |
||||
|
Description=Mosquitto MQTT broker |
||||
|
Documentation=https://mosquitto.org/documentation/ |
||||
|
After=network.target var-lib-virtiofs-data.mount |
||||
|
Requires=var-lib-virtiofs-data.mount |
||||
|
|
||||
|
# Only start once Mosquitto has been configured (the operator provides the password file) |
||||
|
ConditionPathExists=/etc/quadlets/mosquitto/passwd |
||||
|
|
||||
|
# Start/stop this unit when the target is started/stopped |
||||
|
PartOf=mosquitto.target |
||||
|
|
||||
|
[Container] |
||||
|
ContainerName=mosquitto |
||||
|
Image=mosquitto.image |
||||
|
AutoUpdate=registry |
||||
|
|
||||
|
# No need for root privileges: the broker binds 1883 (> 1024) as an unprivileged user. |
||||
|
# The upstream entrypoint only chowns /mosquitto when it runs as root; as UID 10033 it |
||||
|
# just execs the broker, so every directory it touches must already be owned by 10033:10000 |
||||
|
# (that is what tmpfiles.d and the config install ownership take care of). |
||||
|
User=10033 |
||||
|
Group=10000 |
||||
|
|
||||
|
# Network configuration (host networking is the convention across this repository) |
||||
|
Network=host |
||||
|
|
||||
|
# Run the broker against the packaged configuration. Host and container paths are kept |
||||
|
# identical so that password_file, acl_file, persistence_location and include_dir all |
||||
|
# resolve to the same location inside and outside the container. |
||||
|
Exec=/usr/sbin/mosquitto -c /etc/quadlets/mosquitto/mosquitto.conf |
||||
|
|
||||
|
# Configuration (read-only): mosquitto.conf, conf.d/ fragments and the operator-provided |
||||
|
# passwd / acl files all live under /etc/quadlets/mosquitto. |
||||
|
Volume=/etc/quadlets/mosquitto:/etc/quadlets/mosquitto:ro,Z |
||||
|
|
||||
|
# Precious data (retained messages + client sessions) on the virtiofs mount, so the |
||||
|
# host's ZFS snapshots and backups pick it up. |
||||
|
Volume=/var/lib/virtiofs/data/mosquitto:/var/lib/virtiofs/data/mosquitto:z |
||||
|
|
||||
|
# Health check: a bare TCP connect to the listener. It needs no credentials (which the |
||||
|
# operator may not have provided yet), which is why it is preferred over a credentialed |
||||
|
# mosquitto_sub on $SYS/#. |
||||
|
HealthCmd=nc -z 127.0.0.1 1883 |
||||
|
HealthInterval=30s |
||||
|
HealthTimeout=5s |
||||
|
HealthStartPeriod=10s |
||||
|
HealthRetries=3 |
||||
|
|
||||
|
[Service] |
||||
|
Restart=always |
||||
|
RestartSec=10 |
||||
|
TimeoutStartSec=120 |
||||
|
TimeoutStopSec=30 |
||||
|
|
||||
|
[Install] |
||||
|
WantedBy=mosquitto.target |
||||
@ -0,0 +1,11 @@ |
|||||
|
[Unit] |
||||
|
Description=podman pull docker.io/library/eclipse-mosquitto |
||||
|
Documentation=https://hub.docker.com/_/eclipse-mosquitto |
||||
|
|
||||
|
# Only pull if Mosquitto has been configured (the operator provides the password file) |
||||
|
ConditionPathExists=/etc/quadlets/mosquitto/passwd |
||||
|
|
||||
|
[Image] |
||||
|
# The ":2" tag is a multi-architecture manifest (amd64 + arm64, checked 2026-09-19, |
||||
|
# version 2.1.2), which is required to run on the aarch64 target. |
||||
|
Image=docker.io/library/eclipse-mosquitto:2 |
||||
@ -0,0 +1,14 @@ |
|||||
|
[Unit] |
||||
|
Description=Mosquitto Service Target |
||||
|
Documentation=man:systemd.target(5) |
||||
|
Requires=traefik.target mosquitto.service |
||||
|
After=traefik.target mosquitto.service |
||||
|
|
||||
|
# Allow isolation - can stop/start this target independently |
||||
|
AllowIsolate=yes |
||||
|
|
||||
|
# Only start once Mosquitto has been configured (the operator provides the password file) |
||||
|
ConditionPathExists=/etc/quadlets/mosquitto/passwd |
||||
|
|
||||
|
[Install] |
||||
|
WantedBy=multi-user.target |
||||
@ -0,0 +1,31 @@ |
|||||
|
# Traefik dynamic configuration contributed by the mosquitto cookbook. |
||||
|
# |
||||
|
# TLS is terminated HERE (on the https / :443 entry point) and the plaintext MQTT |
||||
|
# stream is forwarded to the broker on loopback. This is a TCP router, not an HTTP |
||||
|
# one. It coexists on the https entry point with the HTTP routers of the other |
||||
|
# cookbooks, which match HostSNI(`*`) implicitly. |
||||
|
# |
||||
|
# In production the SNI host name and the certificate resolver are site values, |
||||
|
# injected by the operator via an overlay into /etc/quadlets/traefik/conf.d/. This |
||||
|
# shipped fragment uses the bare SNI `mqtt` and a self-signed certificate so it is |
||||
|
# testable as-is. |
||||
|
tcp: |
||||
|
routers: |
||||
|
mosquitto: |
||||
|
# A TCP router whose HostSNI is not `*` REQUIRES a tls section (below). |
||||
|
rule: "HostSNI(`mqtt`)" |
||||
|
entryPoints: |
||||
|
- https |
||||
|
service: "mosquitto" |
||||
|
# Bare `tls: {}` makes Traefik serve its own self-signed certificate, which is |
||||
|
# what makes this fragment testable as shipped. In production, uncomment the |
||||
|
# certResolver below to obtain a real Let's Encrypt certificate (site value). |
||||
|
tls: {} |
||||
|
#tls: |
||||
|
# certResolver: le |
||||
|
services: |
||||
|
mosquitto: |
||||
|
loadBalancer: |
||||
|
# A TCP service uses `address:`, never `url:`. |
||||
|
servers: |
||||
|
- address: "127.0.0.1:1883" |
||||
@ -0,0 +1,9 @@ |
|||||
|
variant: fcos |
||||
|
version: 1.4.0 |
||||
|
passwd: |
||||
|
users: |
||||
|
- name: mosquitto |
||||
|
uid: 10033 |
||||
|
gecos: Mosquitto MQTT broker |
||||
|
home_dir: /var/lib/quadlets/mosquitto |
||||
|
primary_group: itix-svc |
||||
@ -0,0 +1 @@ |
|||||
|
d$ /var/lib/virtiofs/data/mosquitto 0700 10033 10000 - |
||||
Loading…
Reference in new issue