mhdhaidarah/samm

By mhdhaidarah

Updated 1 day ago

SAMM for MikroTik ISPs — install via the compose bundle at github.com/mhdhaidarah/samm-docker (don

Image
Networking
Security
Monitoring & observability
0

9.0K

mhdhaidarah/samm repository overview

SAMM — Docker distribution

The official Docker image for SAMM (SecuryTik Active MikroTik Manager) — a FreeRADIUS + PostgreSQL + FastAPI AAA stack for MikroTik ISPs: PPPoE / Hotspot / DHCP-IPoE access, IPv6 dual-stack, plans & limits, double-entry billing with online payments (Stripe / Binance / PayPal) + QuickBooks/Xero export, REST API + webhooks, admin & customer portals, Email/Telegram/SMS/WhatsApp notifications, and an HA replication runbook.

▶ Start here → github.com/mhdhaidarah/samm-docker Don't wire these images up by hand — use the compose bundle from the samm-docker releases. It pins the release version tags (app, freeradius, wa-bridge) and wires the whole stack together, including the optional WhatsApp QR bridge. One-line install below, MikroTik RouterOS container instructions in the docs.

One file, every platform

There's a single docker-compose.yml. It runs the same everywhere — a Linux server (x86 or ARM), Windows Docker Desktop, and MikroTik RouterOS 7.23+ containers (arm64 or x86). The images are multi-arch and pulled by tag, so each machine gets its own CPU architecture automatically. Nothing to choose, no .env, no per-arch file.

Quick install (Ubuntu / Debian)

curl -fsSL https://github.com/mhdhaidarah/samm-docker/releases/latest/download/install.sh \
    | sudo bash

The installer detects Docker, installs it if missing, drops a docker-compose.yml into /opt/samm-docker/ with a strong random database password already filled in, and brings the stack up. No .env — the compose file is the single source of truth (re-runs and auto-updates keep your password).

After ~30 seconds:

  • Admin portal http://<host>:8000/admin
  • Customer portal http://<host>:8000/
  • RADIUS auth UDP 1812 on the host's LAN IP
  • RADIUS accounting UDP 1813 on the host's LAN IP

Default credentials: admin / adminchange on first login.

Windows (Docker Desktop) — evaluation only

You can run SAMM on Windows via Docker Desktop + WSL2. Not recommended for production because:

  • Windows sleep / hibernate / lid-close stops the containers
  • Boot-restart only fires when WSL boots (not on Windows boot)
  • Daily auto-update cron only runs while WSL is alive
  • No 24/7 reliability for RADIUS auth and accounting

Use it for evaluation, then deploy production on a Linux VM or small physical box.

Evaluation steps from PowerShell (no WSL terminal needed; Docker Desktop's WSL backend handles it):

mkdir C:\samm-docker
cd C:\samm-docker
curl.exe -fLO https://github.com/mhdhaidarah/samm-docker/releases/latest/download/docker-compose.yml
# optional: notepad docker-compose.yml and find & replace
#           change-me-strong-random-string with your own password
docker compose pull
docker compose up -d

Watch it boot in Docker Desktop → Containers → the samm stack expands into 8 services. Open http://localhost:8000/admin (login admin / admin).

If MikroTik will hit this Windows host, allow UDP 1812/1813 through Windows Firewall:

New-NetFirewallRule -DisplayName "SAMM RADIUS" -Direction Inbound -Protocol UDP -LocalPort 1812,1813 -Action Allow

Tear down: docker compose down -v (the -v wipes the postgres + Fernet key volumes).

MikroTik (RouterOS 7.23+ container feature)

Run SAMM directly on a MikroTik router — the same docker-compose.yml, no special file. RouterOS 7.23+ pulls the correct architecture from the multi-arch image tags automatically (arm64 on router hardware, amd64 on x86 RouterOS/CHR).

Steps — in WebFig/WinBox:

  1. Install the container package, enable it (/system device-mode update container=yes, reboot), and format a USB/microSD/NVMe disk as ext4.
  2. Container → Apps → + New → YAML, paste docker-compose.yml (from the latest release), set the formatted disk as storage, submit.
  3. RouterOS pulls each image (right arch) and wires the services up.

Sitting at "waiting for reverse proxy"? On RouterOS 7.23+, untick Use HTTPS in the Apps dialog and re-deploy. That option controls how RouterOS serves the app's web UI through its reverse proxy — not how images are pulled — so unticking it is safe.

Full walkthrough (prep, disk formatting, RADIUS wiring) lives at https://samm.securytik.com/docs#doc-install under Option D.

Note for maintainers. MikroTik's compose parser drops the command: field on YAML import. Every SAMM app service therefore carries BOTH command: ["<role>"] and environment: SAMM_ROLE: <role> for the same role; entrypoint.sh reads ${SAMM_ROLE:-${1:-api}} so either source works. Keep both fields in lockstep when adding app services. (wa-bridge needs neither — its role is baked into the image's CMD, which is exactly what makes it RouterOS-proof.)

What it ships

ContainerRole
postgresPostgres 16 on the private compose bridge
samm-apiFastAPI admin + customer portal (exposes :8000)
samm-radiusTime-driven AAA + CoA sender
samm-workerMikroTik inventory + ICMP ping sweep (NET_RAW)
samm-notificationEmail/Telegram/SMS/WhatsApp notification outbox drain
samm-telegramLong-polling Telegram bot
freeradiusStock freeradius/freeradius-server:3, SAMM config mounted
wa-bridgeWhatsApp QR bridge (idles until the QR provider is used) — self-contained multi-arch image

The app + freeradius + wa-bridge images are all mhdhaidarah/samm (tags <ver>, freeradius-<ver>, wa-bridge-<ver>, plus -arm64/-amd64 single-arch variants for RouterOS), pinned by version tag in the compose file and built multi-arch (amd64 + arm64). App source stays closed: it's built from Cython-compiled binaries — no .py source.

WhatsApp QR bridge (optional)

WhatsApp has two providers under Notifications → Channels → WhatsApp:

  • Meta WhatsApp Cloud API (official, recommended) — token + Phone-Number-ID, nothing extra to run; works out of the box.

  • Unofficial QR link (at your own risk) — a small Baileys sidecar that already runs as part of the stack (the wa-bridge service — nothing to enable). Just open the WhatsApp channel, pick Unofficial QR link, and scan the QR. It idles (no linked number, no traffic) until you do.

    The bridge is a self-contained image (mhdhaidarah/samm:wa-bridge-<ver>, multi-arch) with code + deps baked in — so it starts instantly and runs on normal Docker and on MikroTik's RouterOS container feature alike (no bind-mount, no command:). The linked session persists in the wabridge_auth volume; WA_BRIDGE_TOKEN is auto-generated into the compose file. Don't want it running? docker compose stop wa-bridge.

Boot startup

install.sh installs samm-docker.service (systemd, enabled). The stack comes back up after a host reboot even if you had run docker compose down before shutdown. Belt-and-suspenders alongside compose's restart: unless-stopped: the restart policy survives Docker daemon restarts; the systemd unit covers explicit-down + reboot.

Disable: sudo systemctl disable samm-docker.service.

Network

  • Host needs UDP 1812 + 1813 free. Coexisting with a bare-OS SAMM install is not supported — if you previously ran install.sh from mhdhaidarah/samm on this host, apt purge freeradius postgresql before installing the docker variant.
  • The freeradius container exposes 1812 + 1813 via standard compose port mapping (no host networking).
  • MikroTik NAS points to the host's LAN IP on 1812/1813. The shared secret is set in the SAMM admin portal under System → RADIUS.

Upgrading

install.sh sets up auto-update for you:

  • /opt/samm-docker/host-updater.sh — the upgrade script
  • /etc/cron.d/samm-docker — runs host-updater.sh daily at 04:00
  • /var/log/samm-update.log — captures stdout + stderr each run

Each run: query the latest release tag, download the matching docker-compose.yml (carrying your password over), then docker compose pull && docker compose up -d. No-op when nothing's new.

Disable auto-update: sudo rm /etc/cron.d/samm-docker. Change the schedule by editing that file.

Manual upgrade:

sudo curl -fsSL https://github.com/mhdhaidarah/samm-docker/releases/latest/download/install.sh \
    | sudo bash

Re-running install.sh preserves your password and WhatsApp-bridge token; it only refreshes docker-compose.yml and pulls the new image.

Backup

Three volumes carry state worth keeping:

  • samm_pgdata — Postgres data
  • samm_etcsamm — Fernet key (secret.key) and the rendered samm.yaml
  • samm_wabridge_auth — the WhatsApp QR bridge's linked session (losing it just means re-scanning the QR — include it if you use the QR provider)

Losing samm_etcsamm means losing the Fernet key, which means you can no longer decrypt MikroTik API passwords stored in the DB. Back them up together:

sudo docker run --rm \
    -v samm_pgdata:/src/pgdata:ro \
    -v samm_etcsamm:/src/etcsamm:ro \
    -v samm_wabridge_auth:/src/wabridge_auth:ro \
    -v "$(pwd):/out" \
    alpine tar czf "/out/samm-backup-$(date +%F).tar.gz" -C /src .

Docker-variant limitations

These work in the bare-OS install but not in the Docker variant:

  • Staged license lockdown (soft/hard stops on samm-worker etc.) — the in-process license check still throttles the data plane and the reactivation wall in the admin portal still shows, but the lockdown enforcer doesn't stop containers.
  • Dynamic FreeRADIUS config reload — changes via the admin UI require docker compose restart freeradius to take effect.

The WireGuard and Cloudflare Tunnel admin pages are automatically hidden in the docker variant. They manage host-level systemd services that aren't reachable from inside the container; the admin sidebar hides them and the routes redirect with a "configure on the host" notice. Use the bare-OS install if you need built-in VPN / tunnel management.

Multi-arch

The published images are multi-archlinux/amd64 and linux/arm64 under the same tag. Every consumer resolves the right variant from the tag on its own: docker pull / Compose on a normal host (including Apple-silicon Macs, x86 and arm servers), and MikroTik RouterOS 7.23+ on the router itself — RB5009, hAP ax², CCR2004/2116/2216 and similar (arm64), or x86 RouterOS/CHR (amd64). One docker-compose.yml, nothing to choose. The file is plain YAML 1.2 (no merge keys) so RouterOS's parser reads it cleanly.

armv7 devices and the smaller mipsbe/smips MikroTik boards are not supported — the Python/FastAPI/Postgres/freeradius stack needs more headroom than those SKUs provide. The bare-OS install on a small Linux box remains the recommended production path for larger deployments; MikroTik-on-container suits small/branch sites.

Uninstall

cd /opt/samm-docker
docker compose down -v   # -v wipes the postgres volume AND the Fernet key
sudo rm -rf /opt/samm-docker

Support

Built by SecuryTik.

Tag summary

Content type

Image

Digest

sha256:d94892615

Size

57.3 MB

Last updated

1 day ago

docker pull mhdhaidarah/samm:wa-bridge-latest