This documentation is part of the "Projects with Books" initiative at zenOSmosis.
The source code for this project is available on GitHub.
Topic Access Control (ACL)
Relevant source files
Purpose and Scope
This document explains the Access Control List (ACL) functionality available in the protected-no-wildcard branch of this repository. The main branch deploys Mosquitto with anonymous access enabled and no topic restrictions. For production environments requiring user-based topic isolation and access control, the protected-no-wildcard branch provides ACL-based authorization.
For information about the anonymous access configuration in the main branch, see Anonymous Access. For encryption of retained messages, which is also available in the protected-no-wildcard branch, see Encrypted Retained Messages.
Sources : README.md:5-11
Overview
Mosquitto supports Access Control Lists (ACLs) that define which users can publish or subscribe to specific topics. The main branch of this repository uses allow_anonymous true in mosquitto.conf2 permitting unrestricted access to all MQTT topics. This configuration is suitable for trusted environments or development scenarios.
The protected-no-wildcard branch implements a user-based topic hierarchy where the first level of each topic path represents the username, enforced through an ACL file located at mosquitto/aclfile.
Sources : mosquitto.conf:1-6 README.md:5-11
Branch Comparison
Diagram: Configuration Differences Between Branches
| Feature | Main Branch | Protected-No-Wildcard Branch |
|---|---|---|
| Anonymous Access | Enabled (allow_anonymous true) | Disabled |
| ACL File | Not present | mosquitto/aclfile |
| User Authentication | Not required | Required |
| Topic Restrictions | None | Username-prefixed topics |
| Wildcard Searches | Unrestricted | Restricted to user's own topics |
Sources : README.md:5-11 mosquitto.conf2
Accessing the Protected-No-Wildcard Branch
The protected-no-wildcard branch is available as a reference implementation for ACL-based access control. You can view the branch or compare it with the main branch:
- Branch URL:
https://github.com/jzombie/docker-mqtt-mosquitto-cloudflare-tunnel/tree/protected-no-wildcard - Diff URL:
https://github.com/jzombie/docker-mqtt-mosquitto-cloudflare-tunnel/compare/main...protected-no-wildcard
To switch to this branch locally:
Sources : README.md11
ACL Pattern Architecture
The protected-no-wildcard branch implements a hierarchical topic namespace where each user operates within a topic prefix matching their username. This pattern prevents users from accessing topics belonging to other users while allowing full control within their own namespace.
Diagram: Topic Namespace Isolation
graph TB
subgraph "Topic Hierarchy"
root["MQTT Topic Root"]
user1_ns["alice/"]
user2_ns["bob/"]
user3_ns["charlie/"]
user1_devices["alice/devices/+"]
user1_sensors["alice/sensors/+"]
user1_commands["alice/commands/+"]
user2_devices["bob/devices/+"]
user2_sensors["bob/sensors/+"]
end
subgraph "ACL Rules"
acl_file["mosquitto/aclfile"]
rule_alice["user alice\ntopic alice/#"]
rule_bob["user bob\ntopic bob/#"]
rule_charlie["user charlie\ntopic charlie/#"]
end
root --> user1_ns
root --> user2_ns
root --> user3_ns
user1_ns --> user1_devices
user1_ns --> user1_sensors
user1_ns --> user1_commands
user2_ns --> user2_devices
user2_ns --> user2_sensors
acl_file --> rule_alice
acl_file --> rule_bob
acl_file --> rule_charlie
rule_alice -.->|Grants Access| user1_ns
rule_bob -.->|Grants Access| user2_ns
rule_charlie -.->|Grants Access| user3_ns
Sources : README.md7
ACL File Structure
The mosquitto/aclfile follows Mosquitto's ACL file format. Each entry defines permissions for a specific user, restricting their access to topics matching a pattern.
Basic ACL Syntax
user <username>
topic [read|write|readwrite] <topic-pattern>
Example ACL Configuration
# User alice can publish and subscribe to all topics under alice/
user alice
topic readwrite alice/#
# User bob can publish and subscribe to all topics under bob/
user bob
topic readwrite bob/#
# User charlie can only subscribe to charlie/sensors/# but publish to charlie/commands/#
user charlie
topic read charlie/sensors/#
topic write charlie/commands/#
| ACL Directive | Description |
|---|---|
user <username> | Begins an ACL rule block for the specified username |
topic read <pattern> | Grants subscribe (read) permission for matching topics |
topic write <pattern> | Grants publish (write) permission for matching topics |
topic readwrite <pattern> | Grants both publish and subscribe permissions |
# wildcard | Matches all remaining topic levels |
+ wildcard | Matches a single topic level |
Sources : README.md7
Access Control Flow
Diagram: ACL Authorization Flow
Sources : README.md7
Wildcard Search Restrictions
The protected-no-wildcard branch implements a "naive" restriction on wildcard searches. With the username-prefixed topic hierarchy, users are prevented from subscribing to wildcards that would cross user boundaries.
Allowed Wildcards
| Pattern | Description | Allowed |
|---|---|---|
alice/devices/+ | Single-level wildcard within user namespace | ✓ Yes |
alice/sensors/# | Multi-level wildcard within user namespace | ✓ Yes |
alice/+/temperature | Single-level wildcard in middle of path | ✓ Yes |
Blocked Wildcards
| Pattern | Description | Blocked Reason |
|---|---|---|
# | Root-level multi-level wildcard | Would access all users' topics |
+/sensors/# | Wildcard at username level | Would access multiple users' topics |
alice/../bob/sensors/# | Topic traversal attempt | Not valid MQTT topic |
Sources : README.md7
Configuration Changes Required
When migrating from the main branch to the protected-no-wildcard branch, several configuration changes are necessary:
mosquitto.conf Changes
Required Additional Files
- mosquitto/aclfile : Create this file with appropriate user and topic rules
- Password file (if using password authentication): Use
mosquitto_passwdutility to create
Docker Compose Volume Mount
The ACL file must be mounted into the mosquitto container:
Sources : README.md7 mosquitto.conf:1-6
Authentication Methods
With allow_anonymous false, Mosquitto requires authentication. The protected-no-wildcard branch supports several authentication mechanisms:
| Method | Configuration | Use Case |
|---|---|---|
| Password File | password_file /mosquitto/config/passwords | Simple username/password authentication |
| Plugin Auth | auth_plugin /path/to/plugin.so | Database-backed authentication |
| PSK | psk_file /mosquitto/config/psk_file | Pre-shared key authentication |
| Certificate | require_certificate true | TLS client certificate authentication |
The specific authentication method used in the protected-no-wildcard branch should be verified by examining the branch's mosquitto.conf.
Sources : mosquitto.conf2
Security Considerations
Diagram: Security Layer Defense in Depth
Benefits of ACL Implementation
- Topic Isolation : Users cannot access topics outside their namespace
- Wildcard Restriction : Prevents broad topic enumeration by unauthorized users
- Granular Control : Different read/write permissions per topic pattern
- Audit Trail : Clear definition of who can access what
Limitations
- Naive Implementation : The "naive" approach mentioned in the README indicates this is a basic pattern-matching implementation
- Topic Format Dependency : Security relies on clients following the
username/topic prefix convention - No Dynamic ACL : Changes to the ACL file require container restart
- First-Level Only : Security boundary is only at the first topic level
Production Recommendations
For production deployments requiring robust access control:
- Implement strict client validation to enforce topic naming conventions
- Consider additional authentication layers (e.g., OAuth2, JWT)
- Monitor for topic naming violations
- Implement rate limiting per user
- Use TLS client certificates for stronger authentication
- Enable Mosquitto's logging for audit trails
Sources : README.md7
Migration Checklist
When migrating from the anonymous main branch to the ACL-protected branch:
- Review the diff between branches:
https://github.com/jzombie/docker-mqtt-mosquitto-cloudflare-tunnel/compare/main...protected-no-wildcard - Create
mosquitto/aclfilewith user permissions - Update
mosquitto.confto disable anonymous access - Update
mosquitto.confto reference the ACL file - Create authentication mechanism (password file, plugin, etc.)
- Update
docker-compose.ymlto mount ACL file - Update existing MQTT clients to use credentials
- Update client topic subscriptions to use username prefix
- Test access control with multiple users
- Verify wildcard restrictions work as expected
- Update monitoring/alerting for authentication failures
Sources : README.md:5-11
Related Advanced Features
The protected-no-wildcard branch includes additional features beyond ACL:
- Encrypted Retained Messages : Uses gocryptfs to encrypt retained messages at rest (see Encrypted Retained Messages)
- Auto-save Retained Messages : Automatically persists retained messages after every message
These features complement the ACL implementation to provide a more secure MQTT broker deployment.
Sources : README.md:8-9