Nipper

Lightweight, embeddable MQTT broker for BEAM-based edge applications

VersionDocumentationLicense

Nipper is a minimal MQTT v3.1.1 broker designed to run within your Elixir/Phoenix application’s supervision tree. Perfect for edge computing, IoT gateways, and embedded systems where you need local MQTT messaging without the overhead of a separate broker service.

πŸš€ Features

Core MQTT Protocol

Security & DoS Protection πŸ›‘οΈ

Architecture & Performance

Observability & Monitoring

Development & Testing

πŸƒ Quick Start

Installation

Add nipper to your list of dependencies in mix.exs:

def deps do
  [
    {:nipper, "~> 0.1.0"}
  ]
end

Basic Setup

Add to your application’s supervision tree:

defmodule MyApp.Application do
  use Application

  def start(_type, _args) do
    children = [
      # Your existing children...
      Nipper.Supervisor
    ]

    opts = [strategy: :one_for_one, name: MyApp.Supervisor]
    Supervisor.start_link(children, opts)
  end
end

Configuration

Configure in config/config.exs:

config :nipper,
  # Listener configuration
  listeners: [
    default: [
      port: 1883,
      transport: :tcp,
      acceptors: 100,
      max_connections: 10_000
    ]
  ],
  
  # Authentication
  auth: [
    module: Nipper.Auth.AllowAll  # For development
  ],
  
  # Protocol limits
  protocol: [
    max_packet_size: 65_536,
    max_client_id_length: 128,
    default_keepalive: 60
  ],
  
  # Rate limiting (DoS protection)
  rate_limiter: [
    connection_limit: 10,      # connections per minute per IP
    message_limit: 100,        # messages per minute per client
    auth_limit: 5             # auth failures per 5 minutes per IP
  ]

Testing Your Setup

Start your application and test with a simple MQTT client:

# Terminal 1: Start your application
iex -S mix

# Terminal 2: Test with mosquitto_pub/sub
mosquitto_sub -h localhost -p 1883 -t "test/topic" &
mosquitto_pub -h localhost -p 1883 -t "test/topic" -m "Hello, Nipper!"

πŸ“š Advanced Usage

Custom Authentication

Create a custom authentication module:

defmodule MyApp.MqttAuth do
  @behaviour Nipper.Auth

  @impl true
  def authenticate(conn_info) do
    %{client_id: client_id, username: username, password: password} = conn_info
    
    case verify_credentials(username, password) do
      {:ok, user_info} -> 
        {:ok, %{user_id: user_info.id, permissions: user_info.permissions}}
      :error -> 
        {:error, :not_authorized}
    end
  end
  
  defp verify_credentials(username, password) do
    # Your authentication logic here
  end
end

Configure it:

config :nipper,
  auth: [module: MyApp.MqttAuth]

Telemetry Integration

Set up telemetry handlers for monitoring:

# In your application startup
:telemetry.attach_many(
  "mqtt-metrics",
  [
    [:nipper, :client, :connected],
    [:nipper, :client, :disconnected],
    [:nipper, :message, :published],
    [:nipper, :rate_limit, :exceeded],
    [:nipper, :memory_monitor, :warning]
  ],
  &MyApp.TelemetryHandler.handle_event/4,
  %{}
)

Upstream Integration

Configure event streaming to external systems:

config :nipper,
  upstream: [
    enabled: true,
    transport: MyApp.UpstreamTransport,
    producer: [batch_size: 100, batch_timeout: 1000],
    batcher: [max_batches: 10]
  ]

πŸ—οΈ Architecture

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                 Nipper.Supervisor                   β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”‚
β”‚ β”‚   Listener  β”‚ β”‚RateLimiter  β”‚ β”‚ResourceMon  β”‚    β”‚
β”‚ β”‚(ThousandIs.)β”‚ β”‚   (ETS)     β”‚ β”‚ (GenServer) β”‚    β”‚
β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β”‚
β”‚                                                     β”‚
β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”‚
β”‚ β”‚MemoryMon   β”‚ β”‚   Router    β”‚ β”‚  Upstream   β”‚    β”‚
β”‚ β”‚(GenServer)  β”‚ β”‚(Phoenix.PS) β”‚ β”‚ Producer    β”‚    β”‚
β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Key Components

πŸ§ͺ Development

Running Tests

# Unit tests
mix test --exclude integration

# All tests
mix test

# With coverage
mix test --cover

Code Quality

# Static analysis
mix credo --strict
mix dialyzer

# Documentation
mix docs

Benchmarking

# Connection benchmarks
mix run benchmarks/connections.exs

# Message throughput
mix run benchmarks/messages.exs

πŸ“Š Performance

Benchmarks (on modern hardware)

Resource Limits (configurable)

πŸ›£οΈ Roadmap

Version 0.2.0 (Planned)

Version 0.3.0 (Planned)

πŸ› Known Limitations

This is version 0.1.0 - suitable for development and small-scale deployments:

🀝 Contributing

  1. Fork it
  2. Create your feature branch (git checkout -b feature/amazing-feature)
  3. Add tests and ensure they pass (mix test)
  4. Run code quality checks (mix credo, mix dialyzer)
  5. Commit your changes (git commit -am 'Add amazing feature')
  6. Push to the branch (git push origin feature/amazing-feature)
  7. Create a Pull Request

πŸ“„ License

This project is licensed under the MIT License - see the LICENSE file for details.

πŸ™ Acknowledgments


Built with ❀️ for the BEAM ecosystem