SAMM for MikroTik ISPs — install via the compose bundle at github.com/mhdhaidarah/samm-docker (don
9.0K
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.
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.
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:
http://<host>:8000/adminhttp://<host>:8000/Default credentials: admin / admin — change on first login.
You can run SAMM on Windows via Docker Desktop + WSL2. Not recommended for production because:
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).
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:
container package, enable it (/system device-mode update container=yes, reboot), and format a USB/microSD/NVMe disk as ext4.docker-compose.yml (from the
latest release), set the formatted disk as storage, submit.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 BOTHcommand: ["<role>"]andenvironment: SAMM_ROLE: <role>for the same role;entrypoint.shreads${SAMM_ROLE:-${1:-api}}so either source works. Keep both fields in lockstep when adding app services. (wa-bridgeneeds neither — its role is baked into the image's CMD, which is exactly what makes it RouterOS-proof.)
| Container | Role |
|---|---|
postgres | Postgres 16 on the private compose bridge |
samm-api | FastAPI admin + customer portal (exposes :8000) |
samm-radius | Time-driven AAA + CoA sender |
samm-worker | MikroTik inventory + ICMP ping sweep (NET_RAW) |
samm-notification | Email/Telegram/SMS/WhatsApp notification outbox drain |
samm-telegram | Long-polling Telegram bot |
freeradius | Stock freeradius/freeradius-server:3, SAMM config mounted |
wa-bridge | WhatsApp 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 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.
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.
install.sh from
mhdhaidarah/samm on this host, apt purge freeradius postgresql before
installing the docker variant.freeradius container exposes 1812 + 1813 via standard compose port
mapping (no host networking).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 runEach 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.
Three volumes carry state worth keeping:
samm_pgdata — Postgres datasamm_etcsamm — Fernet key (secret.key) and the rendered samm.yamlsamm_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 .
These work in the bare-OS install but not in the Docker variant:
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.
The published images are multi-arch — linux/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.
cd /opt/samm-docker
docker compose down -v # -v wipes the postgres volume AND the Fernet key
sudo rm -rf /opt/samm-docker
Built by SecuryTik.
Content type
Image
Digest
sha256:d94892615…
Size
57.3 MB
Last updated
1 day ago
docker pull mhdhaidarah/samm:wa-bridge-latest