Documentation

SAMM documentation

The complete operator manual — from first install to day-to-day operations.

25 topics 8 sections One-command install
Quick install

Online in minutes, from one command.

Run a single line on a fresh Ubuntu or Debian server — the bootstrapper fetches the latest release and installs the whole SAMM stack for you.

Read the full installation guide
install.sh — bash
curl -fsSL https://samm.securytik.com/install.sh | sudo bash
Playlist Video course Watch SAMM from install to daily operations — a full video course A free, step-by-step YouTube playlist that walks you through installing SAMM and running it day to day — the same ground this manual covers, on video. Watch on YouTube

Getting started

Overview & architecture

SAMM — SecuryTik Active Mikrotik Manager — is a complete ISP management platform for MikroTik PPPoE & Hotspot networks. One installer turns a bare Linux server into a full AAA, billing, and subscriber-management system.

Who SAMM is for

SAMM is built for wireless ISPs, fibre operators, and hotspot providers running MikroTik RouterOS. If you authenticate subscribers over PPPoE, Hotspot, or IPoE/DHCP and need to enforce speed tiers, data caps, expiry dates, and billing — SAMM does all of it from one screen.

IPoE/DHCP subscribers are identified by their DHCP Option 82 circuit-id (the physical access port — the professional ISP way) or device MAC, and the DHCP server's radius-password is simply the router's own RADIUS shared secret, so there is nothing extra to provision.

IPv6 dual-stack is an opt-in option: every subscriber can get IPv6 alongside IPv4. Enable it in the router wizard and choose the delegated (DHCPv6-PD) prefix length — a /56 by default, or anywhere from /48 to /64 — and the IPv6 blocks to hand out. On each Access-Accept SAMM returns a WAN IPv6 pool plus a routed prefix delegated to the subscriber's LAN, so the customer's own router (in route mode) sub-divides it into /64s and runs SLAAC for their devices — the standard ISP prefix-delegation model. It works with PPPoE, Hotspot and IPoE, and a static IPv6 prefix can be pinned per subscriber for business customers.

How it works

SAMM keeps the hot path close to the database. FreeRADIUS handles every authentication and accounting packet; on each accounting Interim-Update it calls PostgreSQL functions directly to accumulate usage and evaluate limits — there is no Python round-trip while subscribers are online.

Four execution surfaces cooperate through the single database:

  • FreeRADIUS (unlang + rlm_sql) — authenticates every packet; on each Interim-Update it accumulates bytes/uptime and evaluates limits inside Postgres.
  • samm-radius — runs time-driven sweeps (expiry, daily reset, speed windows) and is the only process that sends Change-of-Authorization packets.
  • samm-worker — pings routers and syncs MikroTik device metadata over the API.
  • samm-api — the admin & customer portals; admin actions are queued to the database and applied by samm-radius, never sent as CoAs directly.

The five services

ServiceRole
samm-apiAdmin portal + customer self-service portal + REST API
samm-radiusDrains the CoA outbox; runs expiration / daily-reset / speed-window sweeps
samm-workerPings routers; syncs MikroTik device metadata over the API
samm-notificationDelivers email & Telegram notifications through one throttled queue
samm-telegramRuns the interactive Telegram self-service bot

What SAMM does

AAA core

PPPoE & Hotspot authentication, per-user speed enforcement, hybrid CoA.

Plans & limits

Speed tiers plus four independent limits and scheduled speed windows.

Subscribers

PPPoE, Hotspot, and IPoE/DHCP users plus prepaid hotspot voucher cards with printable PDFs.

Billing

Per-plan pricing, automatic invoices, a double-entry receipts/payments/expenses ledger.

Self-service

A customer web portal and a Telegram bot for usage, invoices, and tickets.

Operations

Live MikroTik inventory, role-based admins, backup & restore, bulk tools.

System

Built-in WireGuard VPN, Cloudflare Tunnel, eight languages, themeable UI.

Notifications

Renewal, expiry, quota and receipt alerts over email and Telegram.

The rest of this manual is a how-to for every one of these areas. Use the menu on the left, or start with Installation.

Getting started

Installation

SAMM installs everything it needs — FreeRADIUS, PostgreSQL, nginx, WireGuard, cloudflared, and the five SAMM services — in one step. The installer is idempotent: re-running it upgrades an existing install in place and never overwrites your config or regenerates your database password.

SAMM runs anywhere — pick the install path that fits your network:

Prerequisites

  • A fresh server: Ubuntu 22.04 / 24.04 / 26.04 LTS, or Debian 12 / 13. Server-grade Linux only — desktop variants are not supported.
  • Root / sudo access and an internet connection.
  • systemd, and a host where PostgreSQL can be installed locally (one is set up for you).

Installation

Option A — install with one command

On the server, run:

curl -fsSL https://samm.securytik.com/install.sh | sudo bash

This bootstrap script downloads the latest SAMM release bundle from GitHub, extracts it, and runs the full installer automatically. Done in a few minutes.

If github.com is blocked in your country, use the Cloudflare-hosted mirror instead — same installer, nothing fetched from GitHub. (The standard command above also detects a blocked GitHub and switches to this mirror by itself.)

curl -fsSL https://dl.securytik.com/install.sh | sudo bash

Either way, once the installer finishes, open the admin portal and sign in with these credentials:

Login URLhttp://<your-server>/admin · Usernameadmin · Passwordadmin

Change the admin password immediately after your first login.

Installation

Option B — install manually from a release bundle

Download the latest samm-<version>.tar.gz from the GitHub Releases page, then on the server:

tar -xzf samm-<version>.tar.gz
cd samm-<version>
sudo bash install.sh

You can also deploy from a zip produced on another machine — the installer rsyncs the source into /opt/samm itself:

mkdir -p /opt/samm && unzip samm.zip -d /tmp/samm-bundle
sudo bash /tmp/samm-bundle/samm/install.sh

Or clone the repository to /opt/samm and run sudo bash /opt/samm/install.sh.

Either way, once the installer finishes, open the admin portal and sign in with these credentials:

Login URLhttp://<your-server>/admin · Usernameadmin · Passwordadmin

Change the admin password immediately after your first login.

Installation

Option C — install with Docker Compose

If you'd rather run SAMM as containers — same product, packaged differently — use the Docker Compose distribution at github.com/mhdhaidarah/samm-docker. On any host with Docker available:

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

That installs Docker if it's missing, drops a docker-compose.yml into /opt/samm-docker/ with a strong random database password already filled in, and starts the stack. The image mhdhaidarah/samm is built from the same compiled bundle as the bare-OS install — closed source by construction.

Multi-arch — the same tag ships for linux/amd64 and linux/arm64, and the right variant is selected automatically from the tag: docker pull on any Docker host (Intel/AMD, ARM server, Apple-silicon Mac), and MikroTik RouterOS 7.23+ on the router itself. One file, every platform.

On hosts where piping curl to bash isn't allowed (locked-down boxes, strict egress policies), you can fetch the ready-to-run compose file directly:

git clone https://github.com/mhdhaidarah/samm-docker.git
cd samm-docker
# optional: edit docker-compose.yml and replace change-me-strong-random-string
docker compose up -d

A few features are not yet in the Docker variant (staged license lockdown, dynamic FreeRADIUS reload). The built-in WireGuard and Cloudflare Tunnel admin pages are intentionally hidden in the Docker variant — they manage host-level systemd services that aren't reachable from inside the container. Pick Option A or B above if you need those built in, or run cloudflared / wg-quick on the Docker host directly alongside SAMM. See the Docker variant's README for the full v1 caveats and the manual install path.

On Windows (Docker Desktop) — evaluation only

Not recommended for production. Windows sleep / hibernate / lid-close stops the containers; boot-restart only fires when WSL starts (not on Windows boot); the daily auto-update cron only runs while WSL is alive. Use it for evaluation / demo, then deploy production on a Linux VM (Hyper-V, Proxmox, ESXi) or a small physical box (e.g. a NUC running Ubuntu Server).

Install Docker Desktop for Windows (lets it set up the WSL2 backend on first launch). Then from PowerShell — no WSL terminal needed — grab the compose bundle and start the stack:

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 — replace change-me-strong-random-string with your own password
docker compose pull
docker compose up -d

Watch the stack boot in Docker Desktop → Containers — the samm group expands into 8 services. Once they're all green, open the admin portal and sign in with these credentials:

Login URLhttp://localhost:8000/admin · Usernameadmin · Passwordadmin

Change the admin password immediately after your first login.

If a real MikroTik NAS will hit this Windows host for RADIUS, 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 from the install dir (the -v wipes the postgres volume and the Fernet key — back them up first if you've added data).

Installation

Option D — install on a MikroTik router (RouterOS 7.23+)

Same SAMM, no Linux box needed. If your MikroTik device supports the container package and has a USB drive or microSD attached, you can run the whole stack directly on the router — with the same docker-compose.yml used everywhere else. RouterOS 7.23+ pulls the right CPU architecture from the multi-arch image tags automatically, so there is nothing router-specific to download.

Supported: every container-capable MikroTik router — RB5009, hAP ax², CCR2004-1G-12S+2XS, CCR2116, CCR2216, L009, and similar (arm64), plus x86 RouterOS and CHR (amd64). Not supported: armv7 / mipsbe / smips / tile / ppc devices (hEX, RB750, older RB models) — no container support or too little RAM/CPU for SAMM's stack. RouterOS 7.23 or newer is required (older versions can't select the architecture from a multi-arch tag).

1. Prepare the router

Install the container package (from extra_packages.zip on mikrotik.com/download — upload the matching container-*.npk via Files, then reboot). Then enable container mode (one-time — it activates only after a hard power cycle, not a soft reboot):

/system device-mode update container=yes
# HARD reboot the router (unplug the power) — a soft /system reboot
# will NOT activate the container feature

2. Format and mount the disk (ext4)

Insert a USB drive or microSD (≥ 8 GB recommended — Postgres + image layers add up). On the router:

/disk print
# note the disk slot, e.g. "usb1-part1" or "disk1"
/disk format-drive usb1-part1 file-system=ext4 label=samm

After formatting, verify the disk mounts and is writable:

/disk print detail
# look for "type=ext4" and a mount point like "/usb1-part1"

3. Copy the compose file

One file for every platform. Replace change-me-strong-random-string (the Postgres password — use the same strong value everywhere it appears) and change-me-random-token. Then in WebFig/WinBox: Container → Apps → + New → YAML, paste, set the ext4 disk from step 2 as storage, submit. RouterOS 7.23+ pulls the right CPU architecture from the image tags automatically.

Stuck at "waiting for reverse proxy"? On RouterOS 7.23+, untick Use HTTPS in the Apps dialog and re-deploy — that option controls the app's web-UI proxy, not how images are pulled.
docker-compose.yml
name: samm

services:
  postgres:
    image: postgres:16-alpine
    restart: unless-stopped
    environment:
      POSTGRES_DB: samm
      POSTGRES_USER: samm
      POSTGRES_PASSWORD: change-me-strong-random-string
      TZ: UTC
    volumes:
      - pgdata:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U samm -d samm"]
      interval: 10s
      timeout: 5s
      retries: 12

  samm-api:
    image: mhdhaidarah/samm:latest
    restart: unless-stopped
    command: ["api"]
    environment:
      SAMM_ROLE: api
      POSTGRES_HOST: postgres
      POSTGRES_PORT: 5432
      POSTGRES_DB: samm
      POSTGRES_USER: samm
      POSTGRES_PASSWORD: change-me-strong-random-string
      TZ: UTC
      SAMM_API_HOST: 0.0.0.0
      SAMM_API_PORT: 8000
      SAMM_API_WORKERS: 2
      WA_BRIDGE_URL: http://wa-bridge:8787
      WA_BRIDGE_TOKEN: change-me-random-token
    depends_on:
      postgres:
        condition: service_healthy
    healthcheck:
      test: ["CMD-SHELL", "curl -fsS http://127.0.0.1:8000/health >/dev/null || exit 1"]
      interval: 10s
      timeout: 5s
      retries: 30
      start_period: 30s
    ports:
      - "8000:8000"
    volumes:
      - etcsamm:/etc/samm
      - sammvar:/opt/samm/var
      - sammlogs:/var/log/samm
      - sammlocales:/opt/samm/app/locales

  samm-radius:
    image: mhdhaidarah/samm:latest
    restart: unless-stopped
    command: ["radius"]
    environment:
      SAMM_ROLE: radius  # see samm-api notes — parser-agnostic role hint
      POSTGRES_HOST: postgres
      POSTGRES_PORT: 5432
      POSTGRES_DB: samm
      POSTGRES_USER: samm
      POSTGRES_PASSWORD: change-me-strong-random-string
      TZ: UTC
    depends_on:
      postgres:
        condition: service_healthy
      samm-api:
        condition: service_healthy
    volumes:
      - etcsamm:/etc/samm
      - sammvar:/opt/samm/var
      - sammlogs:/var/log/samm

  samm-worker:
    image: mhdhaidarah/samm:latest
    restart: unless-stopped
    command: ["worker"]
    environment:
      SAMM_ROLE: worker  # see samm-api notes — parser-agnostic role hint
      POSTGRES_HOST: postgres
      POSTGRES_PORT: 5432
      POSTGRES_DB: samm
      POSTGRES_USER: samm
      POSTGRES_PASSWORD: change-me-strong-random-string
      TZ: UTC
    depends_on:
      postgres:
        condition: service_healthy
      samm-api:
        condition: service_healthy
    cap_add:
      - NET_RAW
    sysctls:
      - net.ipv4.ping_group_range=0 2147483647
    volumes:
      - etcsamm:/etc/samm
      - sammvar:/opt/samm/var
      - sammlogs:/var/log/samm

  samm-notification:
    image: mhdhaidarah/samm:latest
    restart: unless-stopped
    command: ["notification"]
    environment:
      SAMM_ROLE: notification  # see samm-api notes — parser-agnostic role hint
      POSTGRES_HOST: postgres
      POSTGRES_PORT: 5432
      POSTGRES_DB: samm
      POSTGRES_USER: samm
      POSTGRES_PASSWORD: change-me-strong-random-string
      TZ: UTC
      WA_BRIDGE_URL: http://wa-bridge:8787
      WA_BRIDGE_TOKEN: change-me-random-token
    depends_on:
      postgres:
        condition: service_healthy
      samm-api:
        condition: service_healthy
    volumes:
      - etcsamm:/etc/samm
      - sammvar:/opt/samm/var
      - sammlogs:/var/log/samm

  samm-telegram:
    image: mhdhaidarah/samm:latest
    restart: unless-stopped
    command: ["telegram"]
    environment:
      SAMM_ROLE: telegram  # see samm-api notes — parser-agnostic role hint
      POSTGRES_HOST: postgres
      POSTGRES_PORT: 5432
      POSTGRES_DB: samm
      POSTGRES_USER: samm
      POSTGRES_PASSWORD: change-me-strong-random-string
      TZ: UTC
    depends_on:
      postgres:
        condition: service_healthy
      samm-api:
        condition: service_healthy
    volumes:
      - etcsamm:/etc/samm
      - sammvar:/opt/samm/var
      - sammlogs:/var/log/samm

  wa-bridge:
    image: mhdhaidarah/samm:wa-bridge-latest
    restart: unless-stopped
    environment:
      WA_BRIDGE_TOKEN: change-me-random-token
      TZ: UTC
    depends_on:
      - samm-api
    volumes:
      - wabridge_auth:/data/auth      # multi-device session — persists the QR link

  freeradius:
    image: mhdhaidarah/samm:freeradius-latest
    restart: unless-stopped
    environment:
      POSTGRES_HOST: postgres
      POSTGRES_PASSWORD: change-me-strong-random-string
      TZ: UTC
    depends_on:
      postgres:
        condition: service_healthy
      samm-api:
        condition: service_healthy
    ports:
      - "1812:1812/udp"
      - "1813:1813/udp"

volumes:
  pgdata: {}
  etcsamm: {}
  sammvar: {}
  sammlogs: {}
  sammlocales: {}
  wabridge_auth: {}      # WhatsApp bridge multi-device session

4. Verify and connect MikroTik to SAMM

Once the SAMM containers are running, open the admin portal in a browser and sign in with these credentials:

Login URLhttp://<router-ip>:8000/admin · Usernameadmin · Passwordadmin

Change the admin password immediately. RADIUS auth + accounting are exposed on UDP 1812 + 1813 on the router itself, so the MikroTik RADIUS client can point at 127.0.0.1 with the shared secret you set in System → RADIUS.

Experimental deployment path. RouterOS's container feature is leaner than Docker Compose — service-name DNS, dependency ordering (depends_on), and live restarts behave differently. If the stack misbehaves on your hardware, fall back to running Docker on a small Linux box (NUC, Pi 4, Linux VM) next to the MikroTik. The same compose file works there with full Compose semantics.

5. Updating — back up and restore by hand

Updating a MikroTik container app deletes your database. RouterOS cannot change an installed app's version in place — the only way is to remove the app and add it again, and removing it deletes everything the app stored, including SAMM's database. Take a backup and download it to your computer BEFORE you remove the app. A backup left on the router is deleted with everything else.

To move a MikroTik container install to a new version:

  1. In SAMM, go to Tools → Backup, create a backup, and download the file to your computer.
  2. On the router, remove the app and add it again with the new version.
  3. Open the fresh SAMM, go to Tools → Backup and restore the file you downloaded.

This applies to the MikroTik container only. On Docker (Linux, Windows, or a Linux VM) an update is docker compose pull then docker compose up -d, and your data is untouched — the volumes live outside the containers and survive.

Installation

Option E — SAMM Server ISO (appliance install)

The SAMM Server ISO turns any empty machine or VM into a ready SAMM server: boot it, choose DHCP or a static IP on the one screen it shows, confirm, and walk away. It installs Ubuntu Server 24.04 LTS (minimized), names the host samm-server, then downloads and installs the latest SAMM release automatically on first boot — the ISO never goes stale. The console shows a SAMM boot splash and a login banner with the server's IP, the admin-panel address and the default credentials, and a samm-tools command gives one-keystroke access to the maintenance tools (health check, database backup/restore, admin password reset).

The ISO erases the machine's first disk. Boot it only on hardware or a VM dedicated to SAMM. If the machine is offline during install, setup simply finishes itself as soon as it gets internet.

Write it to a USB stick (Rufus, balenaEtcher, or dd) or attach it to a VM, boot, and answer the network question. Default logins after install — panel: admin / admin, OS: samm / samm or root / sammchange all of them.

Download SAMM Server ISO 2.2 GB

SHA-2568b6d57e286a4c0524d96b5b4970b57079113e000fc8229f94360410c12f5102e

Installation

Installer reference

Non-interactive options

All prompts can be pre-answered with environment variables, so the installer can run unattended:

VariableEffect
DB_PASSUse this database password instead of an auto-generated one (first install only)
CF_TOKENInstall the Cloudflare Tunnel connector with this Zero Trust token
SAMM_HTTP_PORTForce the nginx listen port (skips the port-80 detection prompt)
SAMM_VERBOSE1 streams raw command output instead of the progress bar
NO_COLOR1 disables colored output
DB_PASS='strong_pw'   sudo bash /opt/samm/install.sh
CF_TOKEN='eyJ...'     sudo bash /opt/samm/install.sh
SAMM_HTTP_PORT=8080   sudo bash /opt/samm/install.sh

What the installer sets up

The installer runs as a live, colored progress display — a percentage bar and a per-phase checklist. Each phase's raw output is captured to /var/log/samm-install.log; on failure the last 30 lines are printed.

ComponentDetails
FreeRADIUS 3Configured with a PostgreSQL backend and dynamic NAS clients; validated with freeradius -CX
PostgreSQLDatabase, schema, and all SQL migrations applied — every migration file is idempotent
Python venvAll dependencies built from requirements.txt; translation catalogs compiled. If the distro's Python doesn't match the compiled bundle, the installer fetches a matching standalone interpreter into /opt/samm/runtime automatically
nginxReverse proxy added additively — existing sites are never removed. Uses port 80 when free; otherwise prompts for an alternate port
5 servicessamm-api, samm-radius, samm-worker, samm-notification, samm-telegram — all enabled as systemd units
WireGuardPackages installed; configured later from System → VPN
cloudflaredBinary always installed; the tunnel token is optional at install or added later from System → Cloudflare Tunnel

All credentials — the database password and the session signing keys — are generated automatically on first install.

Interactive prompts

Any prompts happen up front, before installation begins:

  • Cloudflare token — paste a Zero Trust connector token to publish SAMM online with no open ports, or press Enter to skip and configure it later.
  • HTTP port — if port 80 is already in use, the installer leaves those sites untouched and asks for an alternate port (default 8080).

Install summary

When the installer finishes it prints a summary with the admin URL, the default login, the chosen HTTP port, the database credentials, and the config-file paths:

============================================================
  SAMM is installed and running.
  Admin portal  : http://localhost/admin/login
  Default login : admin / admin   <- CHANGE AFTER FIRST LOGIN
  Config files  : /etc/samm/samm.yaml  /etc/samm/api.env
============================================================

Upgrading

To upgrade, fetch the new source and re-run the installer:

git -C /opt/samm pull        # or unpack a newer release bundle
sudo bash /opt/samm/install.sh

The re-run re-syncs the source, upgrades the venv, re-applies all migrations, reloads the FreeRADIUS and nginx configs, and restarts every service. Your config files and the HTTP port chosen at first install are preserved.

Tip SAMM can also update itself — see Licensing & updates. Enable automatic updates, or apply them on demand, from System → License.
Air-gapped & remote DB SAMM ships only SAMM — FreeRADIUS, PostgreSQL, nginx and the rest are fetched at install time from upstream apt repos, so air-gapped installs must pre-stage those packages. For a remote PostgreSQL, set the DSN in /etc/samm/samm.yaml after install.

Getting started

First steps

Five short tasks take a fresh install to the point where subscribers can connect and be billed.

1 · First login

  1. Open http://<your-server>/admin/ (use the HTTP port from the install summary if it is not 80), or your Cloudflare tunnel URL.
  2. Sign in with admin / admin.
  3. Immediately change the password from System → Admins, or from the profile menu in the top bar.

2 · Add your first router

  1. Go to MikroTik → NAS and click Add Router.
  2. Enter the router's IP, a shortname, and a RADIUS shared secret. For MikroTik devices, optionally add API credentials for live device sync.
  3. On the MikroTik, add a RADIUS server pointing at the SAMM host (ports 1812/1813) with the same shared secret, and enable RADIUS for PPP / Hotspot.

No FreeRADIUS restart is needed — SAMM resolves NAS clients dynamically from the database. See Routers (NAS) for the full procedure, or let the setup wizard configure the MikroTik for you.

3 · Create a plan

A plan defines the speed, the limits, and the price you sell. Go to Users → Plans → New plan. Full field reference: Plans & limits.

4 · Add a subscriber

Go to Users → New customer, fill in the login credentials and pick a plan. The subscriber can connect immediately. For prepaid hotspot access, generate voucher cards instead.

5 · Activate your license

A fresh install runs unregistered at a minimum tier. Open System → License and activate to lift the limits — see Licensing & tiers.

Day-to-day rhythm Add routers → create plans → add subscribers or cards → watch the Dashboard → record payments under Accounting.

Getting started

Migrate from another system

Already running another RADIUS billing system? SAMM reads its data and recreates your plans and subscribers, so you do not retype anything. Subscribers keep their existing service password and expiry date, which means they keep logging in exactly as before.

Go to Tools → Export / Import and pick your old system under Migrate from another system. Like the rest of Tools, it is superadmin-only.

What to upload

Old systemFileWhere it comes from
SAS4 / Radius Manager .sql or .sql.gz A MySQL backup of the old database
Super Speed Radius .sql or .sql.gz A MySQL backup of the old database
Pro Radius .xlsx or .csv Its exported subscriber list — that system offers no backup export

Database backups are often several gigabytes; that is fine, upload the file as-is. Compressed backups do not need unpacking first.

How it works

  1. Upload the file. Nothing is written yet.
  2. Review the preview. It lists the plans and subscribers that would be created, warns about anything it had to skip or correct, and checks the total against your license before you commit.
  3. Choose what happens to usernames that already exist in SAMM — skip them and keep the SAMM record, or update its name and contact from the old system.
  4. Import. Each row is written independently, so a single bad row never rolls back the rest.

What comes across

  • Plans — name, speeds, price, duration and traffic quota where the old system records them.
  • Subscribers — username, service password, name, contact details, expiry date, plan, static IP and MAC.
  • Subscribers disabled in the old system stay disabled.

Billing, invoices, prepaid cards, tickets, accounting and admin logs are deliberately not imported — they belong to the old system's data model and rarely map cleanly.

Values that do not match their column

Real databases are messy: an address typed into the email box, a note in the mobile field, a phone number written on an Arabic keyboard. SAMM checks every value against what its column is supposed to hold. Anything that does not fit is kept out of that field and saved to the subscriber's admin-only notes instead, tagged with where it came from — so nothing is lost and no field is polluted. The preview tells you how many values this affected.

Pro Radius specifics

Pro Radius exports subscribers but not plans, so SAMM works the plans out from each subscriber's service level, taking the speed from its name (a service called "4MBPS" becomes a 4 Mbps plan). Three things are simply not in that file and are set to sensible defaults you should review afterwards:

  • Duration — set to 1 month. Each subscriber's real expiry date is imported unchanged, so this only affects future renewals.
  • Upload speed — set to match the download rate.
  • Price — set to 0.
Review the plans before invoicing After a Pro Radius import, open Plans and set the real price and period for each one. Until you do, those plans bill at zero.

Good to know

  • Run it more than once safely. Re-importing the same file skips everyone already present rather than duplicating them.
  • Your license still applies. If the file holds more subscribers than your tier allows, the preview says so up front and tells you how many would fit — you can upgrade, or import a partial set.
  • Take a backup first if you are importing into an install that already has real data.

Subscribers & plans

Plans & limits

A plan is the service definition assigned to subscribers — it sets the speed, the limits, and the price. Create plans before adding users.

A fresh install already ships 9 ready-to-use plans — eight monthly speed tiers plus an "Expired" throttle plan — so you can sell immediately or create your own. Seeding runs only on first install and never overwrites plans you've added.

Create a plan

  1. Go to Users → Plans.
  2. Click New plan.
  3. Fill in the form and click Save plan.

Each limit is a toggle — enable only the ones you need. The same modal edits an existing plan (open the row's ⋮ menu → Edit).

Plan fields

FieldMeaning
NameUnique plan name, e.g. Home-50M
PriceCharged per billing period when invoicing is used
Download / Upload speede.g. 50M, 512K, 1G — enforced as the MikroTik rate limit
Simultaneous sessionsHow many devices may be online at once on this plan. 1 by default — a second login is refused while the first is still connected. Set 0 for unlimited. A session that stopped reporting is ignored, so a dropped connection never locks the subscriber out
Limit: ExpirationThe subscription ends a fixed period after activation (days/months/hours/minutes)
Limit: QuotaA total data cap (combined, download-only, or upload-only) for the whole subscription
Limit: UptimeA cap on cumulative connected time — the sum of all session durations
Limit: Daily usageA data cap that resets every day at the configured daily-reset time
Unlimited windowQuick-add of one speed window — the full editor lives in the plan's Speed Windows page
IP poolOptional RADIUS Framed-Pool name for address assignment
Auto-renewStart a fresh period on expiry instead of switching plan or disconnecting

The four limits

Each limit is independent and optional. When several are set, SAMM checks them in a fixed order — expiration → quota → uptime → daily — and the first one exhausted decides the action.

LimitTracksOn exhaust
ExpirationCalendar time since activationSwitch to another plan, or disconnect
QuotaTotal bytes usedSwitch to another plan, or disconnect
UptimeCumulative session secondsSwitch to another plan, or disconnect
DailyBytes since the last daily resetThrottle — to speeds you enter, or via a slower plan — until the next daily reset

For each limit you choose what happens on exhaust: pick a next plan to switch the subscriber onto, or leave it as — disconnect —. The daily limit throttles instead of disconnecting: by default you enter the throttle speeds directly (download / upload fields), or pick a slower "next" plan — either way the subscriber reverts to the original plan at the next daily reset automatically.

Speed windows

A speed window overrides the plan's base speed for set hours — for example an unlimited-speed window after midnight. Click a plan row to open its Speed Windows editor, which adds day-of-week control and supports windows that cross midnight. When several windows match, the highest-speed one wins.

Note Throttled or limit-exhausted subscribers are excluded from speed windows — SAMM never lifts speed while a limit is in force.

Two notions of usage

SAMM keeps usage in two places, and never conflates them:

  • Resettable counters — the per-limit state. Zeroed by an admin reset and by the daily reset.
  • Billing counters — non-resettable lifetime totals. Never zeroed, so reports and invoices stay accurate.

Managing plans

The Plans list shows each plan's speed, subscriber count, active limits, and speed windows. From a row's ⋮ menu you can edit, open its speed windows, enable/disable it, jump to its subscribers, or delete it (only when it has no subscribers). Editing auto-renew offers to propagate the change to all current subscribers.

Duplicate copies a plan exactly — speeds, limits, speed windows and price — under a new name, which is far quicker than rebuilding a tariff by hand to change one number. If the name you give is already taken, the next free number is used.

Subscribers & plans

Subscribers

A subscriber (customer / user) is a PPPoE or Hotspot account that authenticates against SAMM. Each subscriber is assigned exactly one plan.

Create a subscriber

  1. Go to Users and click New customer.
  2. Complete the form and save — the subscriber can connect immediately.
FieldMeaning
Username *The PPPoE / Hotspot login name — must be unique
Password *The login password (stored for PAP/CHAP RADIUS auth)
First / Last nameThe subscriber's name
Mobile / Email / AddressContact details — used for notifications and invoices
Plan *The service plan to assign
Expiration overrideOptional manual expiry date instead of the plan's computed one
Auto-renewRenew the plan period automatically on expiry

Create many subscribers at once

New batch users creates a numbered run of accounts in one pass — the usual way to hand a block of logins to a village rollout, a hotel, or a reseller. Choose how many, what number to start at, and how many digits to pad to (3 gives 001, 002, …); everything else — plan, expiration, auto-renew — is filled in once and applied to all of them. They share one password.

The invoice choice applies to each user in the batch separately, so a run of fifty either raises fifty invoices or none, and the total is shown before you commit.

The subscriber list

The Users page lists every subscriber with an at-a-glance status dot, the assigned plan, and how much of each limit is left — daily usage with a progress bar, quota remaining, uptime remaining, and days left. Filter by status (All / Active / Suspended / Expired / Online) or search by username, name or mobile.

The plan-swap badge A single badge is the subscriber's plan. Two badges joined by an arrow mean the subscriber hit their daily limit and is temporarily parked on a throttle plan — they revert to the original at the next daily reset.

Managing a subscriber

Right-click a row — or use the ⋮ menu — for every per-subscriber action:

ActionWhat it does
View / EditOpen the detail page, or edit contact details, password and expiry
Enable / DisableSuspend the account — online subscribers are disconnected
Renew ExpirationAdd the plan's duration on top of any remaining time; generates an invoice if the plan has a price
Reset Uptime / Quota / DailyZero the chosen limit counter
UsageOpen usage graphs and session history
DeleteRemove the subscriber and all their history — active sessions are disconnected first
How actions take effect Resets, plan changes and renewals are queued to an audit log and applied by the samm-radius tick — typically within a few seconds. If the subscriber is online, SAMM also sends a live refresh. See CoA & live changes.

The detail page can also reveal the subscriber's login password behind an eye-toggle (with one-click copy) — handy when a customer asks for their credentials.

The Usage view

The Usage action opens a detailed traffic page for one subscriber, with a 7d / 14d / 30d / 90d period selector. It reports three headline figures — today's traffic (with the upload/download split and minutes online), this month's traffic, and the cumulative online time for the month. Below them is a daily traffic chart of upload against download, and a full session history table: the start and stop time, duration, bytes down and up, the NAS, and the terminate cause of every session.

Bulk operations

To change owner, expiration, status or auto-renew for many subscribers at once — or to delete many — use the Bulk Changes and Bulk Delete tools. To create subscribers in bulk from a spreadsheet, use Export / Import.

Restrict a subscriber to specific routers

A subscriber (or a whole card group) can be pinned to specific NAS routers from its edit form. With no routers selected the account works on any NAS; with one or more selected, authentication is accepted only from those routers — enforced fail-closed inside RADIUS itself. Changing the set disconnects any live session on a now-disallowed router immediately. Combined with By-NAS admin scoping, this is how multi-branch and franchise setups keep each branch's subscribers on that branch's routers.

Subscribers & plans

Hotspot cards

For prepaid Hotspot access, generate a batch of voucher cards instead of individual subscribers. Each card is a username/password pair with its own speed and limits, generated by the thousand and printed for distribution.

Create a card group

  1. Go to Users → Hotspot Cards and click New group.
  2. Fill in the form below and click Create group — SAMM generates every card's credentials automatically.
SectionFields
IdentityUnique group name, description, optional username prefix, how many cards to generate (up to 10,000)
CredentialsUsername and password format (numbers / letters / alphanumeric) and length
Speed limitDownload and upload speed — 256k, 6M, 1G; 0 = unlimited
Limit TransferUnlimited, combined cap, or separate download/upload caps (MB / GB / TB)
Limit TimesUptime cap, expiration after first login, and a group "valid until" shelf date

The expiration counts from each card's first login, while valid until is a hard shelf date — cards cannot be used after it, whether or not they were ever activated.

Managing a group

Open a group's ⋮ menu to enable or disable every card at once, extend the group's "valid until" shelf date, add more cards to the batch, or edit its details. Individual cards can be reset (quota, uptime or expiration) or disabled from the card detail page.

Duplicate group copies every setting exactly and generates the same number of cards with fresh codes — a card code can only ever belong to one card, so a copy is a new print run, not a clone of the old one. It is the fast way to reorder a voucher batch that sold out.

Card statuses

StatusMeaning
UnusedGenerated but never logged in
ActiveIn use, within its limits
ExhaustedA limit (quota, uptime or expiration) has been reached
DisabledManually disabled

Printing & tracking

Open a group to see its cards, print them to a PDF for distribution (the print layout uses your ISP logo from Settings), and review per-card usage. Card traffic also appears in Reports under the Cards tab, and each group has its own accounting view.

Subscribers & plans

Self Service — guests sign themselves in

The opposite of a voucher: nobody prints anything and nobody stands at a desk. A visitor connects to your hotspot, taps Register on the sign-in page, types their name and mobile number, and SAMM sends them a passcode by SMS, WhatsApp or email. They enter it on the same page and they are online — and you keep a named, exportable record of everyone who used the guest network.

Typical venues: restaurants and cafés, hotels and guest houses, expos and trade fairs, conferences, shopping malls, clinics and waiting rooms, gyms, co-working spaces, salons, airport lounges, stadiums, campuses, libraries, car showrooms, wedding venues, resorts and campsites.

Switching it on

  1. Set up a delivery channel first. Notification Center → enable SMS or WhatsApp and send yourself a test message. Nothing else works until one channel does.
  2. Self Service → Settings: tick Allow guests to register themselves, choose which channels to offer, and set how long a passcode stays valid and how long a guest must wait before asking for another.
  3. Leave Passcodes come from on the Self Service card group unless you have a reason to change it — that group decides the speed and how many devices may share one passcode.
  4. Turn the Register tab on for each login design you use — see below. This is the step people miss.

The login page — the step people miss

The Register tab is per login design, and it is off by default. Open MikroTik Manager → the router → Login Page, edit the design you use and tick Allow Self Service. You can reword every sentence a guest sees on the same screen — the Register tab label, the intro line, the two field labels, the button, and the five replies (“your passcode is on its way”, “you already have one”, “please try again later”, “we could not send it”, “sign-up is not available”).

Then press Push — and press it again after every SAMM upgrade. Hotspot sign-in pages live on the router's own flash storage, not on SAMM. Upgrading SAMM does not re-push them, so a router keeps serving its old page — with no Register tab on it — until you push again. SAMM warns you on the Login Page tab when a router is serving pages older than your installed version, and the Self Service page names every router that cannot show the tab and offers to fix them all at once.

The rules that stop abuse

  • One live passcode per number. Asking again while a code is still valid tells the guest to check their messages instead of sending another.
  • Then a waiting period you set, before that number can request a new one.
  • Validity counts from the moment the passcode is sent, not from first login — so a code that sat unused for a week does not still work.
  • A daily cap set by your license (see below). Once it is used up, guests are asked to try again later and passcodes already issued keep working.
  • Every attempt is recorded against the device's MAC address as the router reported it — which a guest cannot fake from their browser.

The license

Self Service is licensed separately from your plan, by how many passcodes a day the install may issue, and it renews on its own date — so you can be on Free with a paid add-on, or on Pro Max with none. Every install gets 10 a day at no charge; Light raises it to 50, Heavy to 200, and Max removes the limit. See pricing.

The Self Service page shows used / allowed for today and says plainly when the allowance is gone. Buy or renew from your dashboard on securytik.com, or ask from System → License and a SecuryTik admin approves it. A passcode that could not be delivered does not use up your allowance.

Network & routers

Routers (NAS)

A NAS (Network Access Server) is a router that authenticates subscribers against SAMM over RADIUS. Every router that carries subscriber traffic needs a NAS record.

Add a router

  1. Go to MikroTik → NAS and click Add Router.
  2. Fill in the fields below and save.
FieldMeaning
NAS IP / hostnameThe router's address, as seen by the SAMM host
ShortnameA friendly label shown across the UI
Typemikrotik unlocks live device sync and config push; other types are RADIUS-only
SecretThe RADIUS shared secret — must match the router exactly, or authentication fails
CoA portUDP port SAMM sends Change-of-Authorization packets to (MikroTik default 3799)
API port / user / passwordMikroTik API credentials SAMM uses to read device info and push config
No restart needed SAMM resolves NAS clients dynamically from the database — adding or removing a router never requires a FreeRADIUS restart.

The NAS list

Every router shows in one table — ID, NAS IP / hostname, shortname, type, a masked secret (click the cell to reveal it), the CoA and API ports, and a live ping result with round-trip time. The search box filters by IP, shortname or description.

Each row's ⋮ menu carries the per-router actions — View Device and Refresh Info (MikroTik only), Edit, Push RADIUS config (MikroTik only), and Delete. Opening a mikrotik-type row jumps straight to its device page.

Discover neighbours

Click Discover neighbors to scan the network for MikroTik devices (via MikroTik's neighbor-discovery protocol) and add them as NAS records without typing each address by hand. A discovered router can be added by IP, or Auto-added — a one-click bootstrap that creates a SAMM management user on the router, pushes a management IP and clears the factory bridge.

Auto-add is for fresh routers The one-click bootstrap is intended for factory-fresh (or reset) devices — on a router that already carries configuration it can overwrite or break the existing setup.

Push RADIUS config to the router

For MikroTik NAS records, the row's ⋮ menu offers Push RADIUS config — SAMM configures the router for you over the API instead of you typing it by hand. You confirm the SAMM server IP (it must be reachable from the router) and the auth, accounting and CoA ports; SAMM then creates or replaces a RADIUS entry on the router:

SettingValue
CommentSAMM — the tag SAMM uses to find and update this entry later
Servicehotspot, ppp
Address / secretThe SAMM host, with the shared secret from this NAS record
Timeout3000 ms
CoA incomingAccepted, on the CoA port you confirmed

The dialog shows a result log when the push finishes.

Configure the MikroTik side

If you configure the router manually instead:

  • Add a RADIUS server pointing at the SAMM host, with the same shared secret, enabled for PPP / Hotspot.
  • Use auth port 1812, accounting port 1813.
  • Accept incoming CoA on port 3799.
  • Set the accounting Interim-Update interval to about 5 minutes (SAMM's wizard default) — this is how often SAMM accumulates usage and evaluates limits; shorter intervals tighten limit latency at the cost of more accounting traffic.

Monitor-only devices

A router added as a monitor appears in the MikroTik inventory and is pinged and synced, but has no RADIUS role — it cannot authenticate subscribers. Use it to keep an eye on routers that aren't subscriber NASes.

Network & routers

MikroTik manager

When a router has API credentials, SAMM manages it directly over the MikroTik API — no WinBox, no SSH. The MikroTik section is a live inventory of every router, and each device opens a detail page with fifteen tabs that configure almost every part of RouterOS from your browser.

MikroTik Monitor

MikroTik → Monitor shows one card per router, laid out as a grid. Each card reports — refreshed by samm-worker and live-polled every 30 seconds — the reachability dot, RouterOS version, CPU load and core count, memory use, active session count, uptime, and the time of the last sample.

A card is tagged either NAS (a router that also authenticates subscribers over RADIUS) or monitor (a device added for monitoring only). Add MikroTik registers a new device; Refresh now forces an immediate poll. Monitor-only cards carry a right-click menu — Open, Edit, Refresh Info, Delete.

The device page — fifteen tabs

Open any device for its full management page. The tabs fall into four groups.

Monitoring

TabWhat it shows
OverviewDevice info, system info, and performance-history charts (CPU, memory, sessions over time)
InterfacesEvery interface with its live state, plus per-interface traffic history
Websites & AppsThree sub-views: Monitor (websites & apps seen on the router with traffic history), QoS (application-aware priority, below), and App Filter (DNS-based content blocking from the catalog)

Manager

The Manager → General tab is the housekeeping page for the device: Identity (the router name), Time (clock, timezone and NTP), and Tools (reboot, ping and other one-click router actions).

Network configuration

TabWhat you configure
BridgeCreate LAN bridges and choose which physical interfaces (ports) belong to each
VLANAdd and manage VLAN interfaces
IPThree sub-tabs — Static (static and dynamic addresses), DHCP client (pull an address from upstream), DHCP server (hand out addresses, with a live lease table)
DNSDNS servers and cache (the app/site content filter lives under Websites & Apps)
WiFi / CAPsMANWi-Fi interfaces with their configurations and security profiles; and the CAPsMAN controller — configurations, provisioning rules and remote CAPs

Services & maintenance

TabWhat you configure
PPPoEPPPoE servers, PPP profiles, IP pools, and the RADIUS accounting interim-update interval
HotspotHotspot servers, hotspot profiles and user profiles, DHCP/IP pools, and the captive-portal login page
InternetWAN uplinks — SAMM-managed WANs and default routes, with any existing non-SAMM WANs shown read-only
FirewallFilter rules, a router-security analysis, connectivity & targets, security modules, and firewall backups — Auto-Security snapshots the firewall before applying and can arm a timed auto-revert, so a ruleset that locks you out rolls back automatically
UpdateRouterOS updates — pick an update channel, check and apply, and review installed packages
WizardThe guided first-time setup, below

The PPPoE interim-update interval

On the PPPoE tab, Interim update sets how often the router sends RADIUS accounting Interim-Update packets to SAMM. SAMM uses those packets to accumulate byte and uptime counters and to evaluate the quota, daily and uptime limits — without them, limit enforcement and the live-session counters stall. The recommended value is 5m.

The Hotspot login page

From the Hotspot tab you manage the captive-portal login page: keep the MikroTik default pages, apply one of the built-in templates, or apply one of your saved designs. SAMM includes a visual design editor and a template gallery — customise a login page and push it straight to the router's hotspot.

Application-aware QoS

The QoS view (a sub-tab of Websites & Apps) turns the apps and sites SAMM already sees on the router into a download-priority plan. Drag each app from the pool into one of eight priority slots — slot 1 is served first under contention, slot 8 last; apps left in the pool are not shaped. Optionally cap any app's download speed (for example 10M) and set a total download ceiling for priority to compete for. Auto-distribute by category arranges everything in one click — messaging first, then AI services, then stores, with everything else below.

When you push, SAMM compiles the slots into a MikroTik queue tree (tagged SAMM:qos, parent=global) with matching packet-mark firewall rules, highest priority first. It is built on the same Websites & App filter catalogue that powers monitoring, so only apps actually seen on the router appear — and removing SAMM QoS strips every SAMM:qos object back off the router, leaving your counters untouched.

The setup wizard

The Wizard tab collects everything in ten short steps and pushes the full configuration to the router in one batch at the end. Nothing is sent until you confirm on the final review step.

  1. Welcome & detect — SAMM probes the router and shows what is already configured, so you can skip those items in the push.
  2. Bridge interface — name the LAN bridge.
  3. Bridge ports — pick which physical interfaces join the bridge.
  4. DNS — set upstream resolvers (one-click presets for Google, Cloudflare, Quad9 and more), cache size, and optionally a DNS content filter.
  5. NTP — set the router's clock source (NTP client, and optionally serve time to the LAN).
  6. Internet — add one or more WAN uplinks (Static / DHCP / PPPoE).
  7. RADIUS to SAMM — point the router at your SAMM host for authentication, accounting and CoA.
  8. Services — choose whether the wizard creates a PPPoE server, a Hotspot server, or an IPoE / DHCP service, and optionally turn on IPv6 dual-stack (opt-in, off by default): pick the delegated (DHCPv6-PD) prefix length and the IPv6 blocks and the wizard builds the pools and attaches them to the PPP profile.
  9. PPPoE / Hotspot details & Firewall — pools, profiles, lease times, the firewall & NAT rules, and an optional Expired pool & internet block that redirects expired subscribers to SAMM's "subscription expired" page instead of a dead connection.
  10. Review & push — see the exact list of commands that will be sent, then push them all to the router.
Per-user speed comes from RADIUS The wizard creates a single PPPoE / hotspot profile — it does not push per-tier profiles. Each subscriber's speed is delivered by SAMM in the RADIUS reply at login, so plan changes never need a router edit.

Network & routers

CoA & live changes

CoA (Change-of-Authorization) is how SAMM changes a subscriber's session while they are online — to lift or drop their speed, or to disconnect them — without waiting for them to reconnect.

How a change reaches a live subscriber

SAMM never pushes a router change straight from a button click. Every admin action follows one safe path:

Admin action Audit log samm-radius tick CoA outbox Router
  1. The action is recorded in an audit log as a queued command.
  2. The samm-radius service drains the queue on its next tick, applies the change, and — if the subscriber is online — enqueues a CoA.
  3. The CoA outbox is drained and the packet is sent to the router.

Time-driven events — expiry, speed-window edges, daily resets — feed the same outbox. The upper bound on latency is one samm-radius tick (30 s by default; lower it in Settings for tighter enforcement).

Hybrid CoA

SAMM sends a CoA-Update first to change the session in place. If the router rejects it after the configured retries, SAMM automatically falls back to a Disconnect-Request — the subscriber reconnects and picks up the new settings. This hybrid strategy works across MikroTik firmware versions.

The CoA Outbox page

Users → CoA Outbox is the live view of that queue. samm-radius is the only sender — the admin panel never pushes a CoA directly — and it drains the queue every tick. The page auto-refreshes every 30 seconds.

Six counters head the page — Pending, Sent, NACK (retrying), Done, Failed and Total. Filter the table by status, by action (update or disconnect), or search by username, NAS IP or reason.

StatusMeaning
pendingQueued, waiting for the next samm-radius tick
sentDispatched (transient — the send and its result are recorded in the same tick, so rows rarely stay in this state)
nackThe router rejected the CoA-Update — SAMM is retrying, then falls back to a disconnect
doneApplied successfully
failedGave up after the retry limit — hover the badge for the last error

Each row shows the user, router, action, attempt count, reason, and the created and sent times. Per-row actions let you Retry a failed or nack'd packet, Cancel one still in flight, or open Attributes to inspect the exact RADIUS attributes the packet carries. The sidebar badge counts pending rows; the Dashboard tracks 24-hour failures. A healthy system keeps this queue near-empty.

Stale-session reaper

If a router crashes or loses connectivity, its Accounting-Stop packets can be lost — and on many systems those subscribers stay "online" forever. SAMM sweeps for sessions that have stopped sending Interim-Updates and closes them automatically (terminate cause Reaped-Stale), so the live-session list, simultaneous-use counts and usage figures stay truthful. The timeout is the stale_session_timeout_seconds setting (default 900 s = 15 minutes; set 0 to disable), and it takes effect live — no restart needed.

Daily operations

Dashboard & live sessions

The two screens under Overview are where you start every shift — the Dashboard for the health of the whole system, Live Sessions for exactly who is connected right now.

Dashboard

Overview → Dashboard is the operator home screen. A period selector at the top — Today, 7d, 14d, 30d, 90d — sets the window for the trend chart and the date-bounded figures.

The six KPI tiles

Each tile is a live counter and a shortcut — click it to jump straight to the filtered list behind the number.

TileShowsOpens
Online nowSubscribers with a live RADIUS session right nowUsers filtered to Online
Active subscribersActive accounts, with the total subscriber count beneathUsers filtered to Active
ExpiredSubscribers whose subscription lapsed with no next plan setUsers filtered to Expired
Open ticketsSupport tickets not yet resolved (excludes done & closed)Users → Support Tickets
RoutersTotal NAS records, plus the count currently unreachableThe MikroTik monitor
Unpaid invoicesInvoices still needing payment follow-upInvoices filtered to Unpaid

Users & live sessions chart

A daily-snapshot line chart plots three series across the selected period — active users, online sessions, and expired users — so growth and churn are visible at a glance.

Pipeline health

This panel is the heartbeat of the enforcement engine. On a healthy system the queues sit at or near zero — a number that stays high points to a stuck service or a router rejecting changes.

MetricWhat it means
samm-radius queuePending CoAs waiting for the next tick — should clear within seconds
Failed CoA (24h)Zero on a healthy system; a non-zero count means a router is rejecting CoAs
Audit log pendingQueued admin actions not yet applied by samm-radius
Sessions throttledSubscribers currently held at a reduced speed by a limit — expected, not an error
Sessions snapshotThe live session count — should track Online now
Active plansThe size of your plan catalogue
The enforcement path Admin actions are queued to samm.audit_log; the samm-radius tick drains them and emits CoAs into samm.coa_outbox. The full path is in CoA & live changes.

Recent-activity tables

Four tables under the chart give a rolling view of what just happened, each with a View all link to its full page:

  • Recent CoA outbox — action, user, status (done / pending / nack / failed), attempt count, reason, and time.
  • Recent admin actions — action, target, the actor who triggered it, whether it is applied yet, and time.
  • Recent subscribers — the newest accounts with their status and last authentication time.
  • Routers — every NAS with a reachable / unreachable / no-data health dot.

Live Sessions

Overview → Live Sessions lists every subscriber the routers currently report as online over RADIUS accounting. The page auto-refreshes every 30 seconds; a manual Refresh button sits in the header.

Filtering the list

  • Search — matches username, framed IP, or NAS IP, submitting as you type.
  • Router — narrow the list to the sessions on a single NAS.
  • Only throttled — show just the subscribers a limit is holding at a reduced speed.
  • Per page — 20, 50, 100 or 200 rows.

What each row shows

ColumnMeaning
UserUsername — links to the subscriber's detail page
Framed IPThe address the router assigned to this session
RouterThe NAS shortname and its IP address
PlanThe subscriber's current plan
Effective speedThe speed enforced on the router right now — the plan speed adjusted by any active speed window. A throttled badge means a limit is holding the subscriber at a reduced speed.
Down / UpLive byte counters for the session
OnlineHow long the session has been up
StartedWhen the session began

Disconnecting a session

The Disconnect button on a row enqueues a CoA-Disconnect for that exact session (reason admin_manual) after a confirmation prompt. The subscriber drops immediately; if their account is still active they are free to reconnect. Track the packet in the CoA Outbox.

Daily operations

Reports & analytics

Overview → Reports is the analytics view — subscriber trends, traffic over time, and the heaviest users and cards on your network.

Choosing the range

Every figure on the page is bound to a date range. Pick a preset — 7d, 14d, 30d, 90d — or type explicit start and end dates and click Apply. A loading overlay covers the page while a long-range query such as 90d runs.

Subscriber & session trends

A line chart with three series over the chosen range: Active subscribers, Online sessions, and Expired subscribers. Use it to spot growth, churn, and the busy hours of your network.

Daily traffic

A stacked bar chart of upload and download bytes per day. Hovering a day shows the upload and download figures plus a combined total in the tooltip footer.

Top 10 lists

Four tables surface your heaviest-traffic accounts, each ranked by volume in GB:

ListRanks
Top 10 download todayLargest download since the last daily reset
Top 10 upload todayLargest upload since the last daily reset
Top 10 download monthLargest download this calendar month
Top 10 upload monthLargest upload this calendar month

Traffic by entity

A paginated, searchable table of per-account traffic. Two tabs switch what it lists:

  • Users — each subscriber with their name, plan, today's upload/download in MB, and this month's upload/download in GB.
  • Cards — each hotspot card with its group, status, and the same today / month traffic split.

The search box filters the table as you type; the per-page selector takes 20 to 200 rows. Every row links through to that subscriber's or card's detail page.

Exporting Reports is an on-screen analytics view. For raw rows to crunch in a spreadsheet, use Tools → Export / Import to download users, plans or NAS as CSV / XLSX.

Daily operations

Accounting & billing

SAMM has a complete double-entry bookkeeping system built in — invoices, expenses, receipts, payments, resellers, fixed assets and full financial statements. There is no separate billing product to integrate, and no accountant needed to keep the books straight.

You never touch debits and credits Every action — recording a payment, adding an expense, selling a card group — posts a balanced journal entry to the ledger automatically. You work in plain terms (invoices, expenses, receipts); SAMM keeps the double-entry books behind the scenes and proves they balance in the Trial Balance.

The Accounting page is organised into eleven tabs.

Overview

The financial snapshot. Four headline figures sit at the top:

FigureMeaning
Cash on handTotal balance across all cash & bank accounts
Money you're owedReceivables — unpaid customer and reseller invoices
Money you owePayables — unpaid expenses
Profit this monthIncome minus expenses for the current month

Below: a table of every cash & bank account with its balance, and an income vs expenses chart over the last 1, 2, 3, 6 or 12 months.

Invoices

An invoice is a bill you issue. Click New invoice and fill in:

FieldMeaning
CustomerType-ahead search for the account being billed
Revenue categoryWhich income account the sale posts to
Issue / Due dateBlank issue date = today; blank due date = the issue date
Tax rate % / tax groupDefaults to the rate in Settings → Billing; assign a tax group to apply several rates (VAT/GST and more) at once, each posting to its own tax account
Line itemsOne or more description / quantity / unit-price rows — subtotal, tax and total compute live

How much to charge — full, segmented, or nothing

Anywhere SAMM is about to bill a subscriber — activating, renewing, changing a plan, extending an expiration, or doing any of those in bulk — the same invoice picker appears, and it shows the money before you commit:

ChoiceWhat it charges
Full invoiceWhole plan periods only — a part period rounds up to a whole one.
Segmented invoiceThe exact time, pro-rating the last part period. The total is rounded to the nearest whole amount, with the difference posted as a rounding adjustment so the books still balance.
No invoiceChange the service and charge nothing — a goodwill extension, a migration, a correction.

Set the length with the periods multiplier for whole plan periods, or type an exact date and let SAMM work out what that costs. Either way the panel shows the line items, the tax and the total as you change them, and Paid records a cash payment for the full amount straight away.

"No invoice" is a right, not a checkbox Charging nothing is a financial decision, so it is gated by a per-role permission in Settings → Admins. It matters most with agents: an agent whose subscribers bill to their own prepaid balance could otherwise renew, change plans and extend expirations all day without ever paying for them. New roles get the right switched off.

Dunning & prepaid wallet

Beyond one-off invoices SAMM automates the whole collection cycle. A dunning schedule sets a bill day, a due day and an automatic block day — with optional late fees — so overdue subscribers are reminded, then cut off, without you watching a spreadsheet. A prepaid wallet mode lets subscribers hold a balance that automatically settles invoices on renewal; they top it up themselves from the customer portal by card or crypto, and every top-up and deduction posts to the ledger.

Invoices are also generated automatically when a subscriber's plan is renewed (from the user's Renew Expiration action or by auto-renew), provided the plan has a price. The list filters by status — unpaid, partial, due, paid — and searches by invoice number or customer. Open any invoice for its detail page and a printable PDF; subscribers can download their own copies from the customer portal and Telegram bot.

Expenses

An expense is money spent running the ISP. New expense records a category (the expense account), the vendor paid, the amount, the date incurred and an optional due date. Each expense has the same unpaid / partial / due / paid lifecycle as an invoice, a detail page, and a printable voucher PDF.

Receipts & Payments

These two tabs record cash actually moving — distinct from the invoice or expense that caused it.

  • Receipts — money in: cash received from a customer, a reseller, or other income, landing in one of your cash accounts. An invoice is the bill; the receipt is the money arriving against it.
  • Payments — money out: cash paid against an expense or to a reseller.

Recording a receipt or payment moves the related invoice or expense toward paid and posts the matching ledger entry.

Customers & Card sales

The Customers tab lists each customer's running balance — what they owe you. Card sales covers prepaid hotspot revenue: it tracks sold card groups and resellers. A reseller buys whole card groups from you on an invoice, then resells the individual cards to end users; their balance owed is what they still need to pay you.

Agents — wholesale billing

An agent sells your service on to end customers on a prepaid wholesale model — think a franchise or a sub-dealer who runs their own book of subscribers but rides on your network. It is entirely optional: if you never create an agent, billing behaves exactly as it always has.

Two debts, cleanly separated The agent owes you the wholesale price (in your books, it is your revenue); the customer owes the agent the retail price (off your books — the agent's own receivable). Your commission is the gap between the two, booked as a trade discount, never as an expense.

Create an agent in Settings → Admins by giving a new admin the built-in Agent role. An agent is a scoped admin login with:

SettingMeaning
Commission %The agent's cut of the retail price (e.g. 40% — you keep 60% as wholesale revenue). Editable per agent, any time.
Credit limitHow far the agent's prepaid balance may go negative before renewals are refused. Set 0 for strict prepaid.
Prepaid balanceTop it up when the agent pays you; each renewal draws the wholesale price from it.

When one of the agent's subscribers renews, SAMM charges the agent's balance the wholesale price, posts your revenue, and raises a real retail invoice to the end customer that is payable to the agent and stays off your ledger. Agent-side dunning — its own switch under Settings → Billing, on by default, with an editable grace period — automatically suspends a non-paying customer (issuing a CoA disconnect); when the agent records the customer's payment, the subscriber reactivates on the spot.

An agent signs in to a scoped view: their own dashboard, a My Balance wallet page, a My Customers list with each customer's invoices and payments, and a My Statement — all limited to their own book. Your company-wide books, other agents and other admins' customers stay hidden.

Assets & Cash accounts

  • Assets — register fixed assets (routers, vehicles, equipment). SAMM tracks their value and depreciation over time.
  • Cash — manage your cash & bank accounts, and your capital accounts: owner's equity, where a contribution is money the owner puts into the business and a withdrawal is money taken out. Capital is not revenue and never appears in Profit & Loss.

Reports — the financial statements

The Reports tab is the accountant's view. Five statements, each date-ranged and exportable to PDF:

ReportAnswers
Profit & LossIncome vs expenses and net profit over a date range. Accrual basis — income counts when invoiced, expenses when incurred, not when cash moves.
Balance SheetAs of a date: what you own (assets) against what you owe (liabilities) plus equity. A balanced badge confirms the two sides match.
Cash FlowPer cash account — opening balance, money in, money out, closing balance over a range.
AgingOutstanding receivables and payables sorted into age buckets, so you can chase overdue invoices and stay ahead of bills.
AdvancedThe raw books: General Ledger (every line on one account with a running balance), Trial Balance (the balanced-books check), the Journal, and an activity log.
The balanced check In the Trial Balance every account's debit and credit columns must total equal — that is the proof the books are sound. If it is ever out of balance, it points to a posting error worth investigating.

Export to accounting software

Under Accounting → Reports → Export, download the books as CSV for QuickBooks, Xero or any spreadsheet: General Journal, Chart of Accounts, Invoices, Trial Balance, Profit & Loss and Balance Sheet. General Journal, Invoices and P&L use the date range; the rest are as-of today. The same data is available over the API at GET /api/v1/accounting/export/{kind} (format=json|csv, scope accounting:read) for BI pipelines and Zapier. Exports exclude voided entries, so a download always reconciles with the on-screen reports.

Daily operations

Undo & approvals

Most mistakes in an ISP panel are money mistakes: the wrong subscriber renewed, a payment recorded twice, a plan changed on the wrong account. SAMM gives you a five-minute undo window on those actions, and — where an action hands money back — a superadmin approval gate before it takes effect at all.

The undo window

Every admin action that moves money or state is recorded as it happens. For the next five minutes the topbar carries an Undo button and an Action history list — click the arrow to reverse the last action, or open the history and jump back to any point within the window. Redo puts it back.

Why only five minutes An undo is not a time machine — it is a safety net for the click you just made. Beyond a few minutes the world has moved on: the subscriber has been online, an invoice has been paid, someone else has edited the record. SAMM would rather refuse than quietly rewrite history, so the step simply leaves your history when the window closes.

An undo refuses — with the reason on screen — when reversing it would destroy something it did not create:

RefusalWhat it means
That record no longer existsThe subscriber, invoice or payment was deleted after your action — there is nothing left to put back.
That record exists againSomething has been re-created in its place; undoing would overwrite the newer record.
This record changed after your actionSomeone else edited it in the meantime — undoing would silently discard their edit.
That step is no longer in your historyThe five-minute window has closed.

Undo is a reversal, not a delete: the original action and its undo both stay in the Audit log, so the record of what happened is never lost. Actions that create something warn you plainly — undoing this will delete what it created — before they run.

The agent approval gate

An agent pays for a subscriber out of their own prepaid balance the moment they activate one. That makes reversing an action a way of getting money back — and a way to cheat: activate a subscriber, let them use the whole month, then delete them on the last day and reclaim the charge.

So SAMM splits an agent's actions by which way the money moves:

DirectionExamplesBehaviour
Costs the agent money Activate, renew, change plan, collect a customer payment Immediate. An agent's day job never waits for anyone.
Hands money back Undo, delete a subscriber, delete an invoice, void a collection Parked as a request. Nothing changes until a superadmin approves it.

Gated actions do not half-happen. The request is stored with everything needed to carry it out later, and approving replays it through the same code the agent would have run — never a second implementation that could drift from the first. Rejecting leaves the world exactly as it was, and the agent keeps the charge.

Working the queue

Requests land in Accounting → Agents Approval with the agent, the action, what it refers to and how much money it returns — the number that makes the decision. Filter by agent or status, search, tick several and approve or reject them together; a rejection can carry a short reason, which the agent sees.

Delegate it Reviewing agents all day is rarely the superadmin's job. The Agents Approval right can be granted to any role in Settings → Admins, so the person who actually does the reviewing gets exactly that power — and nothing else. Creating and managing agents stays superadmin-only. Nobody can decide their own request.

What the agent sees

An agent gets a My Account → Pending Approvals page listing everything they have asked for: what is still waiting, and what was approved or rejected — with the reviewer's reason. Without it a refusal would be indistinguishable from a request that vanished, and they would simply ask again.

They can withdraw their own pending requests — one at a time or several at once — because asking for something you cannot unask is its own trap. A withdrawn request never ran, so nothing changes; a decided one is history and stays. An invoice waiting on review also says so on its own page, so an agent who clicked Delete and saw nothing happen understands why.

For your subscribers

Online payments

SAMM can let your subscribers pay their own invoices online — by bank card (Stripe or PayPal) or with crypto / USDT (Binance). When a subscriber pays, SAMM marks the invoice paid, records it in your books, and — if they were cut off for non-payment — reconnects them automatically. You are never charged: each gateway uses your own account, so the money goes straight to you.

Turn it on (any gateway)

  1. Open Financial → Online payments (superadmin only).
  2. Click a gateway to expand it — Stripe, PayPal or Binance / USDT.
  3. Fill its fields, tick Enable this gateway, and click Save. SAMM won't let you save until the required fields are filled.
  4. Click Run test to confirm your credentials work.
  5. Done — your subscribers now see a Pay button on their unpaid invoices in the portal (and on the "subscription expired" page).

You can enable more than one gateway — the subscriber chooses which to use.

Stripe — bank cards, worldwide

  1. Create a free account at stripe.com. Keep Test mode on while you try it out.
  2. Go to Developers → API keys and copy the Secret key (it starts with sk_).
  3. In SAMM, expand Stripe, paste the Secret key, choose the currency and the cash account that receives it, then Save and Run test.
  4. Recommended: add a webhook so payments confirm reliably. In Stripe go to Developers → Webhooks → Add endpoint, set the URL to https://YOUR-SAMM/pay/webhook/stripe, choose the event checkout.session.completed, then copy its signing secret (whsec_…) into SAMM's Webhook signing secret field.
Going live Test mode works anywhere. Receiving real money through Stripe requires a Stripe-supported country and a linked bank account.

PayPal — cards & PayPal balance

  1. Create a PayPal Business account, then at developer.paypal.com create a REST App and copy its Client ID and Secret.
  2. In SAMM, expand PayPal, paste the Client ID and Client secret, choose Sandbox (testing) or Live, then Save and Run test.
  3. Recommended: add a webhook at developer.paypal.com → your App → Webhooks, URL https://YOUR-SAMM/pay/webhook/paypal, subscribe to CHECKOUT.ORDER.APPROVED and PAYMENT.CAPTURE.COMPLETED, then paste the Webhook ID into SAMM so incoming notifications are cryptographically verified.

Binance / USDT — crypto, works everywhere, no bank needed

This is the best option where cards and PayPal are not available. Your subscribers send USDT; SAMM watches your Binance account and marks the invoice paid automatically. You need three things: an API Key, an API Secret, and a place to receive — a wallet address and/or a Binance Pay ID.

Step 1 — create a read-only API key

Safety first Create the key with reading access only. Never enable Withdraw or Trade — SAMM only needs to read your incoming payments, never move funds.
  1. Log in to Binance → open Account → API Management (or search "API Management").
  2. Click Create API → choose System generated → name it e.g. "SAMM" → finish the security check.
  3. Binance shows the API Key and the Secret Key — copy both now (the Secret is shown only once).
  4. Click Edit restrictions and keep only "Enable Reading" ticked. Leave Spot Trading and Withdrawals OFF. (Optional: restrict the key to your server's IP address.)
  5. Paste the API Key and API Secret into SAMM's Binance card (Key first, then Secret — the same order Binance shows them).

Step 2 — get your receiving wallet address

  1. In Binance go to Wallet → Spot → Deposit (Deposit Crypto).
  2. Choose the coin USDT.
  3. Choose the networkTRC20 is the cheapest and most common; BEP20 and ERC20 also work. Use the same one you select in SAMM.
  4. Copy the deposit Address and paste it into SAMM's On-chain receiving wallet address field. Make sure SAMM's Network dropdown matches the network you chose.

Step 3 — (optional) Binance Pay ID

For subscribers who prefer Binance Pay (instant, no network fee): in the Binance app open Pay and note your Pay ID (your email or phone also works). Paste it into SAMM's Binance Pay ID field. Subscribers can then pay by Pay ID as well as on-chain.

Finally, tick Enable, click Save, then Run test (it checks the key can read your account). You're live.

Exact amount, correct network A subscriber must send the exact amount SAMM shows (the last small digits identify their invoice) on the correct network. A different amount or the wrong network will delay or lose the payment.

What the subscriber sees

  1. They log in to the customer portal → My invoices.
  2. On an unpaid invoice they click Pay (or "Pay · Stripe" / "Pay · Binance" if several are enabled).
  3. Card: they're taken to the gateway's secure page. USDT: they see the exact amount, your address with a QR code, and/or your Pay ID.
  4. Once paid, the invoice turns Paid, it posts to your books, and if they were expired they're reconnected automatically — expired subscribers even get a "Pay & reconnect" button on the expired page.
Your books stay exact Every online payment posts one balanced double-entry (Dr Cash / Cr Accounts Receivable) and records the method (Stripe / Binance) on the invoice, in the payment history, and on the PDF — so you always know how each payment arrived.

Daily operations

Support tickets

SAMM has a built-in help desk. Subscribers raise tickets from the customer portal or the Telegram bot, an admin can open one on a subscriber's behalf, and your team works them all from Users → Support Tickets.

The ticket queue

The queue lists every ticket — number, customer, subject, priority, status, the opened and last-updated dates, and the message count. Filter it with:

  • Status chips — one per ticket status, each carrying a live count, so the workload is visible at a glance.
  • Priority — Normal, Moderate or Critical.
  • Active / Withdrawn — a customer can withdraw a ticket they no longer need; withdrawn tickets are dimmed and hidden by default.
  • Search — by ticket number, subject, or customer.

The sidebar badge counts open tickets so nothing is missed.

Opening a ticket

New ticket lets an admin raise a ticket for a chosen customer — pick the customer, then set a subject, priority and description. Subscribers also open their own from the customer portal or the Telegram bot.

Working a ticket

Open a ticket to read the full conversation thread. From there you can:

  • Reply to the customer — a public message the subscriber sees on their portal and through the Telegram bot.
  • Add an internal note — a staff-only message, hidden from the customer, for handover notes between your team.
  • Change the ticket's status and priority.

Right-click any row — or use its ⋮ button — for the same status, priority, reply and internal-note actions without leaving the queue.

Daily operations

Notification Center

SAMM keeps subscribers informed automatically — over email, Telegram, SMS and WhatsApp — and lets you broadcast messages. The samm-notification service delivers everything through one throttled queue. The System → Notification Center page has six tabs.

Overview

The landing tab — live counts (queued, sending, sent today, failed, skipped, opted-out), the state of each delivery channel, and a feed of the most recent notifications.

Channels

Configure how messages leave SAMM. Email uses its own notification account, kept separate from the password-recovery SMTP in Settings. Telegram uses a bot token, SMS goes through a generic HTTP gateway or Twilio, and WhatsApp uses the official Meta WhatsApp Cloud API (created in Meta for Developers), with an optional unofficial QR-linked bridge at your own risk — the bridge installs in one click on a bare-OS server and ships as a ready-to-run container on Docker. All channel secrets are stored Fernet-encrypted. Each subscriber, from the customer portal, picks which channels they want and can opt out entirely.

Messages

The message templates, one set per event. Edit the wording of any notification — renewal reminders, receipts, and the rest — so every message goes out in your own voice and language.

Rules & Timers

This tab governs when and how automatic notifications fire. For each event you control:

  • Whether the rule is on.
  • Ignore opt-out — when set, the message reaches every subscriber even if they opted out. Reserve it for important transactional messages.
  • Timing — for example, how many days before expiry a renewal reminder is sent.
  • Delivery & throttling — the worker drains the queue one batch per tick; the batch size and tick interval together pace how fast messages go out, so a large broadcast never floods your mail server.

The events SAMM can emit on its own include the renewal reminder (before a subscription expires), the expiry notice (when it lapses), the quota warning (as a data cap runs low), the payment receipt (when a payment is recorded), and plan renewed.

Broadcast

Send a one-off message — a maintenance window, a price change — to a chosen set of subscribers. The broadcast flows through the same throttled queue as automatic notifications.

Outbox

Every message SAMM has queued or sent, with its per-message delivery status, so you can confirm a notification reached the subscriber or see why it did not.

System

WireGuard VPN

SAMM can run a WireGuard VPN server on the SAMM host — typically for remote-admin access into the SAMM box and management access to the MikroTiks behind it. It is managed entirely from System → VPN; no shell needed.

Server tab

  1. Click Generate Keys to create the server keypair. The Server Public Key appears once generated — clients need it.
  2. Set the Listen Port (UDP, default 51820), the Server Tunnel Address (the CIDR on the wg0 interface, default 10.254.254.1/24), and the Client IP Range — the start and end addresses SAMM hands out to new peers automatically.
  3. Turn on Enable WireGuard VPN and click Save — SAMM brings the wg0 interface up. The toggle is locked until server keys exist.

Clients tab

Click Add Client, give the peer a name, and SAMM assigns it the next address from the client range. For each peer you can download its config file, scan a QR code with the WireGuard mobile app, or copy ready-made MikroTik RouterOS commands to bring a router onto the VPN. Peers can be toggled on/off or deleted; status colours show whether each is connected, stale, or never seen.

Regenerating keys is destructive Regenerate Keys changes the server keypair. Every already-deployed client config has the old server public key baked in and will stop connecting until you re-hand-out the updated config. The UI gates this behind a type-to-confirm dialog.

System

Cloudflare Tunnel

A Cloudflare Zero Trust tunnel publishes SAMM to the public internet without opening any firewall ports — useful when the SAMM host sits behind NAT. It is managed from System → Cloudflare Tunnel.

Service status

The page opens on a status card that reports the connector's state:

StateMeaning
RunningThe tunnel is active and forwarding traffic
StoppedConfigured but not currently running
Not configuredThe binary is present — paste a token to set it up
Not installedRe-run install.sh to install the cloudflared binary

It also shows the cloudflared version and whether the connector is set to auto-start at boot.

Configure the tunnel

  1. In the Cloudflare Zero Trust dashboard (one.dash.cloudflare.com), open Networks → Tunnels and Create a tunnel.
  2. Choose the Cloudflared connector, name the tunnel, and save. On the install step, copy only the token — the long string after --token.
  3. Paste it into SAMM and click Configure Tunnel. SAMM hands the token to cloudflared and starts the connector.
  4. Back in Cloudflare, add a Public hostname: your chosen address, type HTTP, URL localhost:80 (proxied by nginx — recommended) or localhost:8000 (direct to the API).

Within a few seconds the status badge turns green and SAMM is reachable on the public hostname. Once configured, one-click actions let you Start, Stop or Restart the connector, Replace Token to rotate it, or Remove tunnel (a type-REMOVE-to-confirm action).

No open ports, token never in the database The tunnel makes an outbound connection to Cloudflare's edge — no firewall port is ever opened on the server. The token is forwarded to cloudflared and stored under /etc/cloudflared/; SAMM never persists it in the database. TLS terminates at Cloudflare's edge, so SAMM itself runs plain HTTP on the loopback.

System

Settings

System → Settings holds the live, hot-reloadable tunables. The daemons re-read them on their next tick — no service restart is needed. Settings are organised into tabs.

General tunables

SettingDefaultControls
samm-radius interval30 sHow often time-driven events are evaluated and CoAs sent
samm-worker interval5 sRouter ping + MikroTik API sync cadence
Acct interim interval60 sThe accounting interval pushed to routers
Daily reset time00:00When daily usage counters roll over
Server timezoneUTCTimezone for speed windows and the daily reset
CoA default port3799Default UDP port for CoA packets
CoA retry max3Retries before the Disconnect-Request fallback

Lower the samm-radius interval for tighter enforcement; raise it to reduce load.

ISP identity, logo, currency & billing (the ISP tab)

Everything most operators ask "where do I change this?" lives on System → Settings → ISP. Edit a field and click Save — the change is live immediately (no restart) and flows onto invoices, receipts, PDFs and the customer portal.

What you changeWhere it shows
ISP nameInvoices, receipts, hotspot cards, portal header
Support phone & emailInvoices and printed hotspot cards
Tax / registration numberPrinted on invoices
ISP logo (upload PNG/JPEG)Auto-resized; appears on invoice/receipt PDFs and printed hotspot cards. Use the ✕ on the preview to remove it.
Currency code (e.g. USD)The ISO currency on invoices and the ledger
Currency symbol (e.g. $)Every amount shown in the admin UI, customer portal and PDFs
Tax on/off, label & rateAdds a VAT/GST line to invoices (e.g. label VAT, rate 11 = 11%)
Change the money symbol To switch the currency shown everywhere (e.g. from $ to £ or a local symbol), set Currency symbol on the ISP tab and Save — it updates the admin panel, the customer portal and all PDFs at once. Set the Currency code (USD, EUR, …) alongside it for the ISO code printed on invoices.

Privacy — anonymous install statistics

When SAMM checks for updates it can send SecuryTik a random install ID, the SAMM version, your plan tier and a coarse country (from your IP, via Cloudflare) — no subscriber or customer data. It only helps us count active installs and prioritise support and languages. Turn it off any time under System → Settings → Privacy; see the privacy policy.

Email tab

Configure the SMTP server used for password-recovery codes sent to admins and customers (host, port, SSL/STARTTLS, username, from-address, password). Click Test connection to verify the credentials without sending mail.

Two email accounts The Email tab here is only for OTP / password recovery. The account used for customer notifications is configured separately in the Notification Center.

System

Admins & roles

System → Admins manages who can sign in to the admin portal and what each person can do. It has two tabs: Admins and Roles.

Admin accounts

Create an admin with a username, password, optional email, and a role. From a row's ⋮ menu you can edit the role or password, disable the account, or delete it. Only a superadmin can manage other admins — and three areas (Admins, Tools and API) are superadmin-only: they can never be granted to a custom role and show as locked in the matrix.

Roles & permissions

A role grants per-area access. The built-in superadmin role always has full access and cannot be changed. Create custom roles for limited access — a new role starts with no access until you set its permissions.

A second built-in role, Agent, is locked and cannot be edited or deleted: it turns the admin into a wholesale reseller with a prepaid balance, a commission split and a customer book scoped to just their own subscribers. See Accounting & billing → Agents for the full model.

For each area of SAMM (subscribers, plans, NAS, accounting, settings, and so on) a role is set to one of three levels:

LevelMeaning
Not allowedThe area is hidden from the sidebar entirely
ViewRead-only access
EditFull access — create, change, delete

Two rights sit beside the area levels, because each one is a money decision rather than a screen:

RightWhat it allows
Allow "No Invoice" Change a subscriber's service — renew, change plan, extend — and charge nothing for it. Off by default on every new role.
Allow Agents Approval Review and decide the requests agents file to reverse a charge. Creating and managing agents stays superadmin-only. See Undo & approvals.
The dashboard is never taken away Whatever else a role is denied, every admin keeps their own dashboard and profile — a login that lands on a permission error is a broken login, not a secure one.

Data-visibility scope

Each role also has a scope. See all customers & cards means the role sees every record. With it unticked, the role is By-NAS scoped: a superadmin assigns specific routers to each admin ("NAS access" in the admin's ⋮ menu), and that admin sees only the subscribers and card groups pinned to those routers — ideal for branches, franchises, or resellers. Subscribers a By-NAS admin creates are pinned to their routers automatically.

License is always reachable The System → License page is a normal permission block — but whenever the device is in a lockdown state (grace, soft or hard) SAMM forces it reachable for every signed-in admin regardless of role, so the recovery path is never walled off.

System

Tools

The Tools section bundles bulk and maintenance utilities. It acts on the entire dataset, so it is available to superadmins only.

Backup & Restore

Create a full database snapshot before any major change. A backup is a gzipped pg_dump archive stored on the server, each with a SAMM header.

  • Create backup — optionally add a note; tick Skip usage & history for a smaller, faster dump that omits bulky log tables.
  • Download a backup to your PC, or upload a previous SAMM backup back to the server.
  • Restore overwrites the current database — gated by a type-RESTORE-to-confirm dialog.

High availability

For a deployment with no single point of failure, run SAMM across two nodes: PostgreSQL streaming replication (a primary with a seconds-behind hot standby) plus a standby AAA node, and promote + repoint on failure. The full operator runbook — replication setup, planned and unplanned failover, failback, an optional synchronous-replication mode, and a post-failover verification checklist — ships as docs/HA.md with the source. Note that replication is not a backup (a bad delete replicates instantly), so keep the scheduled backups above running too.

History Cleaner

Permanently delete old log and history rows to reclaim database space. Pick a retention preset and confirm. The cleaner trims closed RADIUS sessions, post-auth records, daily-usage rollups, router/interface history, limitation logs, applied audit entries, and finished CoA rows. It never touches live sessions, queued commands, pending CoAs, or the non-resettable lifetime usage totals.

Take a backup first History Cleaner deletes permanently. Run a backup before cleaning if you might want the data later.

Export / Import

Bulk export and import for Users, Plans and NAS as .csv or .xlsx. Download a template (the right columns plus a sample row) or a snapshot of current data, fill it in, and upload it back. Every row is validated and shown on a preview screen — duplicates and invalid rows are surfaced, and you choose whether to skip duplicates or update them in place — before anything is written.

Bulk Changes

Apply one change — owner, expiration date, status, auto-renew, or whole plan periods — to every subscriber matching a filter, in a single run. Pick the change, build the filter (status / plan / owner / search), review the matching list, and confirm.

Add whole plan periods is the renewal-in-bulk option: each subscriber gains that many periods of their own plan, so a 7-day plan gains 7 days per period and a monthly plan gains a calendar month — on the same run, without splitting the list by plan first. Subscribers whose plan has no expiration period are skipped rather than guessed at. Add days remains available where you want a flat number of days and no counter reset.

Speed Boost

Raise or lower the speed of whole plans at once by a percentage — a holiday weekend at double speed, or an emergency throttle while a backhaul is degraded. It takes effect immediately, for new logins and for sessions already online.

ControlWhat it does
PercentagePositive multiplies, negative divides: +100% → double speed, −100% → half speed, −500% → a sixth of it. Speed never reaches zero.
Plans to boostTick any number of plans; each row shows the plan rate, the boost in force and the effective speed right now.
Revert automatically afterHours until the boost lapses on its own. 0 keeps it until you reset it by hand.
A boost outranks a speed window The boost is measured from the plan rate and replaces any speed window while it is live — a plan on a 20M night window does not become 40M, it becomes whatever the boost makes of its plan rate. Windows resume the moment the boost lapses.

A subscriber who has exhausted a limit is never lifted back to full speed by a boost. For the same reason, a plan used as a throttle target is skipped by Select all and labelled as such — boosting it would speed up exactly the people you are throttling. You can still tick it by hand if that is what you intend. Reset everything to normal removes every boost and puts live sessions back on their plan speed.

Bulk Delete

Permanently delete many subscribers or hotspot cards at once, selected by filter. Deleting a subscriber also removes their usage history, sessions, RADIUS accounting and invoices, and disconnects any live session. Gated by a type-DELETE-to-confirm dialog.

System

Languages & themes

Languages

The admin and customer portals are fully translatable. Eight languages ship built in: English, Arabic (right-to-left), Russian, Persian (right-to-left), Turkish, French, Spanish and German. Each user picks their language from the top bar or their profile; the choice is remembered per account.

The translation editor

A superadmin can edit translations live from System → Translations — no restart, no file editing. The editor also creates entirely new languages and imports/exports translation workbooks as .xlsx, so you can localise SAMM into any language you serve.

Themes

SAMM ships 16 visual themes, light and dark. Each user picks a theme from the top bar; the preview updates instantly and is saved per account. IT terminology is never translated, so technical screens stay precise in every language.

System

Audit log

System → Audit Log is the record of admin actions — and the command queue that carries them out. When you reset a counter, change a plan, or renew a subscriber, SAMM writes the action here rather than touching a live router directly.

Each entry shows the action, its target, the admin who triggered it, when it happened, and whether it has been applied yet. The samm-radius service drains pending entries on its next tick and, where needed, emits a CoA to refresh a live session. The sidebar badge counts entries still pending; the Dashboard's pipeline-health panel tracks the backlog.

Why a queue Routing every admin action through the audit log means changes are applied by exactly one process in a predictable order — there is never a race between the web portal and a router.

Licensing

Licensing & tiers

Each SAMM installation is licensed per device — the plan lives on that install, so you can run several SAMM servers, each on its own tier. The tier sets three numeric caps.

TierAAA usersHotspot cardsNAS / routers
Unregistered252001
Free1005002
Plus5002,0003
Pro2,0005,0005
Pro Maxunlimitedunlimitedunlimited

A fresh install runs unregistered at the minimum floor. Every feature is available at every tier — the tier only sets the caps. Creating a subscriber, card or NAS past the cap is blocked until you upgrade; no data is ever lost.

Activate & upgrade

  1. Open System → License.
  2. Activate by signing in with your SecuryTik account — or use Link this device, which shows a code you approve on samm.securytik.com without typing your password on the server. The device activates on Free.
  3. To go higher, request Pro or Pro Max from the same page — a SecuryTik admin reviews and approves it.

The License page also re-checks the license on demand and shows your current usage against each cap. Unlink device drops the install back to the unregistered tier without deleting any data.

If a paid license lapses

SAMM never deletes data. A lapsed license steps down gracefully:

StageWhat happens
WarningA reminder banner; everything keeps running
GraceA short window to reactivate; subscribers stay online
Soft lockdownBackground services stop; RADIUS keeps authenticating for about 7 days
Hard lockdownServices stop except the reactivation page

Reactivating at any stage restarts every service automatically — all subscriber data and history are intact.

Automatic updates

Auto-update is independent of licensing — every tier updates, and a lapsed license never blocks it. SAMM checks for a new signed release daily. From System → License you can switch between notify (the default — a banner with an Apply now button) and auto (apply unattended). Each update is verified, backed up, and applied in place. You can also re-run the installer at any time — it upgrades idempotently.

For your subscribers

Customer portal & bot

SAMM gives every subscriber two self-service surfaces — a web portal and a Telegram bot — so they can check usage and pay without contacting you.

The customer portal

Subscribers sign in at the SAMM site root (/) with their SAMM username and password. The portal has:

PageWhat the subscriber sees
OverviewAccount status, plan, expiry, today's and this month's usage, any outstanding invoice
Usage & sessionsTotal downloaded/uploaded, uptime budget, and full session history
My plansThe current plan plus the catalogue of available plans
My invoicesBilling history with one-click PDF download
Support ticketsOpen and follow support tickets
ProfileEdit contact details, change password, set language & theme, manage notifications

From Profile, a subscriber connects their Telegram account, orders their preferred notification channels, or opts out of notifications entirely. If they forget their password, an OTP code is emailed to them (this needs the Email tab configured).

The Telegram bot

The samm-telegram service runs an interactive self-service bot. A subscriber sends /start, verifies once with their SAMM username and password (the bot deletes the password message immediately), and can then, entirely from chat:

  • Check their plan, quota, usage and expiry date
  • View and download invoices as PDF
  • Update their profile and change their password
  • Open and follow support tickets

The bot also delivers the automatic notifications — renewal reminders, expiry notices, quota warnings and receipts — to subscribers who connected Telegram.

The expired-subscriber landing page

When a subscriber expires, the router (configured by the wizard's "Expired pool & internet block") redirects their browser to a friendly "subscription expired" page served by SAMM on port 81 — with your ISP logo and a login button into the portal — instead of a silently dead connection.

System

REST API

System → API manages the public /api/v1 interface. The API is dormant until you create the first token, so an install that never uses it exposes nothing. Everything below is also available as interactive OpenAPI documentation — with a try-it console and full request/response schemas — on your own install at /api/v1/docs.

Interactive docs (Swagger UI)

Every install serves a live API console at /api/v1/docs — reachable straight from the API panel in the admin portal. Click Authorize, paste a token, and any endpoint can be executed against your own data with Try it out; each call shows the real response plus a ready-to-copy curl command.

Every endpoint declares a complete, typed schema — request bodies and responses alike — so field names, types and examples are visible without calling anything. The same schema is served as machine-readable OpenAPI at /api/v1/openapi.json, which generates a fully typed client in the language of your choice:

openapi-generator-cli generate \
  -i https://YOUR-SAMM/api/v1/openapi.json \
  -g python -o ./samm-client

Quick start

  1. Open System → API (superadmin only), pick a name, an expiry and the scopes the integration needs, then click Create token.
  2. Copy the secret immediately — it is shown exactly once and only its hash is stored on the server.
  3. Verify it works and see what the token can do:
curl -H "Authorization: Bearer samm_YOUR_TOKEN" https://YOUR-SAMM/api/v1/me

List active subscribers, then create one:

curl -H "Authorization: Bearer samm_YOUR_TOKEN" \
  "https://YOUR-SAMM/api/v1/customers?status=active&limit=20"

curl -X POST -H "Authorization: Bearer samm_YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"username":"john","password":"secret1","firstname":"John",
       "lastname":"Doe","plan_id":3}' \
  https://YOUR-SAMM/api/v1/customers

Authentication, tokens & scopes

Every request sends Authorization: Bearer <token>. A token carries a name, a per-minute rate limit, an expiry (30–360 days or never) and a set of scopes — per-resource read/write grants; a write scope automatically includes the matching read. The secret is shown exactly once; the server stores only a hash. A token can be revoked (calls fail immediately, reversible) or deleted outright.

Responses follow one set of conventions: list endpoints take limit/offset and return {"total", "items"}; errors use standard status codes — 401 missing/invalid/expired token, 403 missing scope, 404 not found, 409 duplicate, 422 validation error, and 429 when the rate limit is hit (with Retry-After and X-RateLimit-* headers).

Endpoint reference

AreaEndpointsScope
Introspection GET /me · GET /commands any token
Dashboard stats GET /stats/overview stats:read
Subscribers GET/POST /customers · GET/PATCH/DELETE /customers/{id} · POST …/suspend · …/activate · …/renew · …/reset-limit · …/assign-plan · GET …/usage customers:read/write
Disconnect POST /customers/{id}/disconnect · POST /sessions/disconnect · /sessions/reconnect coa:write
Plans GET/POST /plans · GET/PATCH /plans/{id} plans:read/write
Invoices GET/POST /invoices · GET /invoices/{id} · GET /invoices/{id}/pdf · POST …/pay · …/unpay billing:read/write
Accounting books GET /accounting/export · GET /accounting/export/{kind} accounting:read
Live sessions GET /sessions · GET /coa-outbox sessions:read
Routers GET /routers routers:read
Hotspot cards GET/POST /cards/groups · GET /cards/groups/{id} · GET …/cards · …/print.pdf · POST …/cards · …/enable · …/disable · …/extend · GET /cards/{id} · POST /cards/{id}/enable · …/disable · …/reset/{kind} cards:read/write
Webhooks GET/POST /webhooks · DELETE /webhooks/{id} · POST …/enable · …/disable · …/test webhooks:manage

Queued commands

Mutations that touch live accounting state — limit resets, card and group enable/disable, validity extensions — are not applied inside the request. They are queued into the audited command queue and applied by samm-radius within one tick (a few seconds), exactly like the same clicks in the admin portal. Such endpoints reply {"queued": true}; poll GET /commands to see your token's queued commands flip to applied.

Webhooks

Register an endpoint URL and pick events (customer created/updated/renewed/expired, limit exhausted, invoice created/paid, optional session events). The signing secret is returned once at creation. Deliveries are retried with backoff, and an endpoint that keeps failing is disabled automatically — re-enable it with POST /webhooks/{id}/enable or send yourself a sample event with POST /webhooks/{id}/test.

Every delivery carries X-SAMM-Event and X-SAMM-Signature: sha256=HMAC(body). Verify before trusting:

import hmac, hashlib

def verify(body: bytes, signature_header: str, secret: str) -> bool:
    calc = "sha256=" + hmac.new(secret.encode(), body,
                                hashlib.sha256).hexdigest()
    return hmac.compare_digest(calc, signature_header)
Same rules as the portal API mutations go through the same audited command queue and service layer as the admin portal — a reset or plan change via the API behaves exactly like one clicked in the UI, CoA and all.

Reference

Operating SAMM

Almost everything is done from the admin portal. This page is the shell reference for the rare times you need it.

Service management

# Restart all SAMM services
systemctl restart samm-api samm-radius samm-worker samm-notification samm-telegram

# Live logs for one service
journalctl -u samm-api    -f
journalctl -u samm-radius -f

# Validate the FreeRADIUS config after any change
freeradius -CX

# Port 8000 stuck after a crash (admin portal unreachable)
kill -9 $(lsof -ti:8000); systemctl restart samm-api

Admin CLI

For quick subscriber operations from the shell. Each command is queued to the audit log and applied on the next samm-radius tick — exactly like the UI actions.

CLI="sudo -u samm /opt/samm/venv/bin/python -m samm_radius.cli"

$CLI reset-quota      alice          # reset a limit counter
$CLI reset-daily      alice
$CLI reset-uptime     alice
$CLI reset-expiration alice
$CLI change-plan      alice home-50M # switch a subscriber's plan
$CLI encrypt-pw                       # encrypt a router API password for the DB

Configuration files

FileHolds
/etc/samm/samm.yamlThe database DSN, connection-pool sizes, log level
/etc/samm/api.envPortal session secrets and the password-recovery SMTP settings
/etc/samm/secret.keyThe encryption key for stored router API passwords

These files are preserved across upgrades and never overwritten by a re-run of the installer. Runtime tunables (loop cadences, daily-reset time, CoA ports) live in Settings instead, and apply with no restart.

Updating SAMM

Either let SAMM update itself from System → License, or re-run the installer — see Installation → Upgrading. Both paths re-apply migrations and restart services; your config and data are untouched.

Backup & recovery

Use Tools → Backup & Restore for a full database snapshot before any major change. To rebuild on a fresh host, install SAMM and then restore the backup.

Maintenance tools (external)

Some maintenance jobs are destructive enough that they do not belong in the admin panel, where a stray click could destroy a live business. SAMM keeps them as standalone, root-only scripts you download and run deliberately from the shell — never as a button. They live in the public distribution repository under tools/.

Reset a locked-out admin password

Locked out of the admin panel? Set a new password for a superadmin account straight in the database — no working login needed. It also re-enables the account if it was disabled, and touches nothing else.

curl -fsSL -o samm-reset-admin-password.sh \
  https://raw.githubusercontent.com/mhdhaidarah/samm/main/tools/samm-reset-admin-password.sh

sudo bash samm-reset-admin-password.sh --list   # list the superadmin accounts
sudo bash samm-reset-admin-password.sh          # reset (prompts for the new password, twice)

Run it as root on the SAMM server. If there are several superadmins, pass --user <name> to choose one.

Reset the books (wipe financial data)

Clears every financial transaction so an ISP can start its accounting from zero, while leaving all subscriber and AAA data completely intact. Useful when taking over an install, or after a trial/testing period, when the books are full of data the operator wants gone but the customer base must stay exactly as it is.

Danger — irreversible data loss This permanently destroys all invoices, payments, receipts, wallet balances and ledger history. There is no undo. The only way back is a database backup. Never run it on a production install you have not backed up and verified first.

Removed: invoices and their line items, the double-entry ledger (payments, receipts, adjustments, wallet top-ups and withdrawals), online-payment transactions, expenses, fixed assets and the accounting activity log. Invoice numbering resets, so the next invoice starts at #1.

Kept: every subscriber, plan, speed window, limit, usage counter, plan history, hotspot card, router, session and RADIUS accounting record — plus your accounting configuration (chart of accounts, cash accounts, tax groups, payment gateways). Cash, wallet and receivable balances are derived from the ledger, so they simply read zero afterwards.

Download it, read it, then run it. Always do a dry run first:

curl -fsSL -o samm-wipe-financials.sh \
  https://raw.githubusercontent.com/mhdhaidarah/samm/main/tools/samm-wipe-financials.sh

sudo bash samm-wipe-financials.sh --dry-run   # show what would be deleted, change nothing
sudo bash samm-wipe-financials.sh             # do it
Do not pipe it straight into a shell Never run this as curl … | sudo bash. For a script that destroys data you want to read it first, and a truncated download must not be able to execute half a wipe. Download, inspect, then run.

The script refuses to run as a non-root user, prints exactly what it is about to delete, then asks you to type YES to confirm you hold a verified backup and WIPE to proceed. It offers to take its own database dump first (into /var/backups/samm/) and aborts if that dump fails. The wipe runs as a single all-or-nothing transaction, and RADIUS is deliberately left running throughout, so subscribers stay online while the books are cleared.

Reference

FAQ & troubleshooting

What operating systems does SAMM support?

Ubuntu 22.04 / 24.04 / 26.04 LTS and Debian 12 / 13. Server-grade Linux only — desktop variants aren't supported. The installer expects systemd, a fresh PostgreSQL install (one is set up for you), and root access.

Do I need an internet connection to run SAMM?

No. SAMM runs entirely on your own server and authenticates subscribers locally over RADIUS. The only outbound traffic is a periodic license heartbeat to the SecuryTik license server so your plan stays validated.

Can I run SAMM in the cloud, or does it need to be on-prem?

Either works. Most operators run on-prem next to their core routers; some run on a small cloud VM with a Cloudflare Zero Trust tunnel back. The only requirement is that the MikroTik routers can reach the SAMM server on the RADIUS ports (1812/1813 UDP) and that SAMM can reach the routers over the MikroTik API.

Do I have to restart FreeRADIUS when I add or remove a router?

No. SAMM resolves NAS clients dynamically from the database, so adding, editing or removing a router in MikroTik → NAS takes effect with no restart.

How fast does a plan change or counter reset take effect?

Admin actions are queued and applied by the samm-radius service on its next tick — within 30 seconds by default. If the subscriber is online, SAMM also sends a live CoA to refresh the session. Lower the samm-radius interval in System → Settings for tighter timing.

What happens to my data if a paid license lapses?

Nothing is ever deleted. A lapsed license steps down through warning, grace, a soft lockdown (RADIUS keeps authenticating for about a week) and finally a hard lockdown. Reactivating at any stage restarts every service with all data intact.

Is SAMM free? What does Pro add?

The Free tier is free forever and includes every feature. Plus, Pro and Pro Max don't unlock features — they raise the caps on AAA users, hotspot cards and routers. See Licensing & tiers.

A subscriber can't authenticate — where do I start?

Check that the router's RADIUS shared secret matches the NAS record exactly, that the router is enabled for PPP / Hotspot RADIUS, and that the subscriber's account is Active and not expired. Watch journalctl -u samm-api -f and the FreeRADIUS log, and confirm the router can reach the SAMM host on UDP 1812/1813.

Need more help?

Email [email protected] to report a bug or request a feature.