Skip to main content
The m87 server can be self-hosted for on-premise deployments, giving you complete control over your device management infrastructure.

Overview

m87-server handles device registration, authentication, and tunnel relay. It connects m87 runtimes on edge devices to m87 CLI users. Self-hosting allows you to:
  • Keep all device data within your infrastructure
  • Customize authentication and access control
  • Meet compliance requirements
  • Control updates and maintenance windows

Requirements

  • MongoDB: Version 8 or later (for device and user data storage)
  • Docker (recommended): For containerized deployment
  • TLS Certificate: For production deployments (Let’s Encrypt or custom)
  • Public IP/Domain: For device and client connectivity

Quick Start with Docker Compose

1

Clone the Repository

2

Configure Environment

Create a .env file with your configuration:
Edit the .env file with your settings (see Configuration below).
3

Start the Server

This will start:
  • m87-server (API and tunnel relay)
  • MongoDB (database)
  • Watchtower (optional auto-updates)
4

Verify Deployment

Check that services are running:

Configuration

The m87 server is configured via environment variables. Below are the key settings:

Core Database

MONGO_URI
string
required
MongoDB connection string used by m87-serverDefault: mongodb://mongo:27017
MONGO_DB
string
default:"m87-server"
Logical database name used by m87-server
MONGO_INITDB_ROOT_USERNAME
string
MongoDB root username (required for secured MongoDB setups)
MONGO_INITDB_ROOT_PASSWORD
string
MongoDB root password (required for secured MongoDB setups)

Authentication & OAuth

OAUTH_ISSUER
string
required
OAuth/OIDC issuer URL used to validate access tokensDefault: https://auth.make87.com/
For custom auth, use your Auth0 tenant or OIDC provider.
OAUTH_AUDIENCE
string
required
Expected OAuth audience for access tokens (must match the aud claim)Default: https://auth.make87.com

Server Networking

PUBLIC_ADDRESS
string
required
Public base address where this server is reachableDefault: localhost
Used to check SNI of incoming requests for device ID prefixes.
UNIFIED_PORT
string
default:"8084"
Port for the unified public interface (runtime connections and tunnel traffic)
This should be mapped to port 443 for TLS.
REST_PORT
string
default:"8085"
Port for the REST API
Used for WebTransport endpoint for the web app (typically mapped to 8080).

Admin & Security

ADMIN_KEY
string
required
Static admin API key for privileged actions
Used for approving users, creating organizations, and bootstrapping admin access.
Change this from the default value in production!
ADMIN_EMAILS
string
Comma-separated list of email addresses that receive admin privileges

User Management

USERS_NEED_APPROVAL
boolean
default:"false"
Whether newly registered users require manual approval
  • true: User accounts start inactive until approved
  • false: Users are active immediately
USER_AUTO_ACCEPT_DOMAINS
string
Domains that are auto-approved on signup
Comma-separated list (no spaces). If a user’s email domain matches, approval is skipped.

Device Sharing

ALLOW_CROSS_ORG_DEVICE_SHARING
boolean
default:"false"
Whether devices can be shared across different organizations
  • true: Cross-org device sharing allowed
  • false: Devices are restricted to their organization

Data Retention

AUDIT_RETENTION_DAYS
number
default:"30"
Number of days audit log entries are retained
Older entries are automatically deleted.
REPORT_RETENTION_DAYS
number
default:"7"
Number of days deployment/report data is retained
Older reports are automatically deleted.

Other Settings

STAGING
number
default:"1"
Whether the server runs in staging mode
  • 0: Production behavior
  • 1: Staging mode with relaxed checks and verbose logging
RUST_LOG
string
default:"info"
Logging level
Options: error, warn, info, debug, trace
CERTIFICATE_PATH
string
default:"/data/m87/certs/"
Path for TLS certificates

Exposed Ports

The docker-compose configuration exposes:
  • 4438084 (TCP/UDP): Runtime connections and tunnel traffic (TLS)
  • 80808085 (UDP): REST API and WebTransport endpoint

Example Configuration

Here’s a complete example .env file for production:

Building from Source

If you prefer to build the server binary yourself:
1

Install Rust

Requires Rust 1.85 or later:
2

Clone and Build

Binary will be at: target/release/m87-server
3

Run with MongoDB

Ensure MongoDB is running, then:

Using Prebuilt Docker Images

Pull the latest image from GitHub Container Registry:
Or specify a version:

Auto-Updates with Watchtower

The docker-compose file includes Watchtower for automatic updates:
Watchtower will:
  • Check for new images every 5 minutes
  • Automatically pull and restart with latest version
  • Only update containers with the watchtower.enable label

Production Deployment Checklist

1

Secure MongoDB

  • Set strong MONGO_INITDB_ROOT_PASSWORD
  • Restrict MongoDB port access (only to m87-server)
  • Enable MongoDB authentication
2

Configure TLS

  • Obtain TLS certificate (Let’s Encrypt recommended)
  • Configure reverse proxy (nginx, Caddy) or mount certificates
  • Ensure port 443 routes to UNIFIED_PORT
3

Set Admin Credentials

  • Change ADMIN_KEY from default
  • Configure ADMIN_EMAILS
  • Set USERS_NEED_APPROVAL based on your requirements
4

Configure Authentication

If using custom OAuth:
  • Set up OAuth provider (Auth0, Keycloak, etc.)
  • Update OAUTH_ISSUER and OAUTH_AUDIENCE
  • Ensure tokens include required claims
5

Set Public Address

  • Update PUBLIC_ADDRESS to your domain
  • Ensure DNS points to your server
  • Verify firewall allows ports 443 and 8080
6

Configure Monitoring

  • Set appropriate RUST_LOG level
  • Set up log aggregation
  • Monitor container health
7

Backup Strategy

  • Configure MongoDB backups
  • Backup certificate files
  • Store .env configuration securely

Client Configuration

After deploying your server, configure clients to use it:
Clients will need to authenticate against your OAuth provider.

Troubleshooting

Check logs:
Common issues:
  • MongoDB connection failed (check MONGO_URI)
  • Invalid OAuth configuration
  • Port already in use
Verify:
  • PUBLIC_ADDRESS is correct and DNS resolves
  • Port 443 is accessible from internet
  • TLS certificate is valid
  • Firewall allows incoming connections
Check:
  • OAUTH_ISSUER and OAUTH_AUDIENCE match your provider
  • OAuth provider is reachable
  • Tokens include required claims
  • Admin key is correct
  • Verify MongoDB is running: docker compose ps mongo
  • Check MongoDB logs: docker compose logs mongo
  • Ensure credentials in .env match MongoDB config

Updating

Manual Update

With Watchtower (Automatic)

If running with the auto-update profile, Watchtower handles updates automatically.

License

The m87 server is licensed under AGPL-3.0-or-later.

Support

For issues and questions: