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
Service
Role
samm-api
Admin portal + customer self-service portal + REST API
samm-radius
Drains the CoA outbox; runs expiration / daily-reset / speed-window sweeps
samm-worker
Pings routers; syncs MikroTik device metadata over the API
samm-notification
Delivers email & Telegram notifications through one throttled queue
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:
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.)
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:
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:
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.
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:
In SAMM, go to Tools → Backup, create a backup, and
download the file to your computer.
On the router, remove the app and add it again with the new
version.
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 / samm —
change all of them.
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.
Component
Details
FreeRADIUS 3
Configured with a PostgreSQL backend and dynamic NAS clients; validated with freeradius -CX
PostgreSQL
Database, schema, and all SQL migrations applied — every migration file is idempotent
Python venv
All 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
nginx
Reverse proxy added additively — existing sites are never removed. Uses port 80 when free; otherwise prompts for an alternate port
5 services
samm-api, samm-radius, samm-worker, samm-notification, samm-telegram — all enabled as systemd units
WireGuard
Packages installed; configured later from System → VPN
cloudflared
Binary 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
Open http://<your-server>/admin/ (use the HTTP port from the
install summary if it is not 80), or your Cloudflare tunnel URL.
Sign in with admin / admin.
Immediately change the password from System → Admins,
or from the profile menu in the top bar.
2 · Add your first router
Go to MikroTik → NAS and click Add Router.
Enter the router's IP, a shortname, and a RADIUS shared secret. For MikroTik
devices, optionally add API credentials for live device sync.
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 system
File
Where 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
Upload the file. Nothing is written yet.
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.
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.
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
Go to Users → Plans.
Click New plan.
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
Field
Meaning
Name
Unique plan name, e.g. Home-50M
Price
Charged per billing period when invoicing is used
Download / Upload speed
e.g. 50M, 512K, 1G — enforced as the MikroTik rate limit
Simultaneous sessions
How 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: Expiration
The subscription ends a fixed period after activation (days/months/hours/minutes)
Limit: Quota
A total data cap (combined, download-only, or upload-only) for the whole subscription
Limit: Uptime
A cap on cumulative connected time — the sum of all session durations
Limit: Daily usage
A data cap that resets every day at the configured daily-reset time
Unlimited window
Quick-add of one speed window — the full editor lives in the plan's Speed Windows page
IP pool
Optional RADIUS Framed-Pool name for address assignment
Auto-renew
Start 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.
Limit
Tracks
On exhaust
Expiration
Calendar time since activation
Switch to another plan, or disconnect
Quota
Total bytes used
Switch to another plan, or disconnect
Uptime
Cumulative session seconds
Switch to another plan, or disconnect
Daily
Bytes since the last daily reset
Throttle — 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
Go to Users and click New customer.
Complete the form and save — the subscriber can connect immediately.
Field
Meaning
Username *
The PPPoE / Hotspot login name — must be unique
Password *
The login password (stored for PAP/CHAP RADIUS auth)
First / Last name
The subscriber's name
Mobile / Email / Address
Contact details — used for notifications and invoices
Plan *
The service plan to assign
Expiration override
Optional manual expiry date instead of the plan's computed one
Auto-renew
Renew 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:
Action
What it does
View / Edit
Open the detail page, or edit contact details, password and expiry
Enable / Disable
Suspend the account — online subscribers are disconnected
Renew Expiration
Add the plan's duration on top of any remaining time; generates an invoice if the plan has a price
Reset Uptime / Quota / Daily
Zero the chosen limit counter
Usage
Open usage graphs and session history
Delete
Remove 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
Go to Users → Hotspot Cards and click New group.
Fill in the form below and click Create group — SAMM generates
every card's credentials automatically.
Section
Fields
Identity
Unique group name, description, optional username prefix, how many cards to generate (up to 10,000)
Credentials
Username and password format (numbers / letters / alphanumeric) and length
Unlimited, combined cap, or separate download/upload caps (MB / GB / TB)
Limit Times
Uptime 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
Status
Meaning
Unused
Generated but never logged in
Active
In use, within its limits
Exhausted
A limit (quota, uptime or expiration) has been reached
Disabled
Manually 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
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.
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.
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.
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
Go to MikroTik → NAS and click Add Router.
Fill in the fields below and save.
Field
Meaning
NAS IP / hostname
The router's address, as seen by the SAMM host
Shortname
A friendly label shown across the UI
Type
mikrotik unlocks live device sync and config push; other types are RADIUS-only
Secret
The RADIUS shared secret — must match the router exactly, or authentication fails
CoA port
UDP port SAMM sends Change-of-Authorization packets to (MikroTik default 3799)
API port / user / password
MikroTik 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:
Setting
Value
Comment
SAMM — the tag SAMM uses to find and update this entry later
Service
hotspot, ppp
Address / secret
The SAMM host, with the shared secret from this NAS record
Timeout
3000 ms
CoA incoming
Accepted, 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
Tab
What it shows
Overview
Device info, system info, and performance-history charts (CPU, memory, sessions over time)
Interfaces
Every interface with its live state, plus per-interface traffic history
Websites & Apps
Three 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
Tab
What you configure
Bridge
Create LAN bridges and choose which physical interfaces (ports) belong to each
VLAN
Add and manage VLAN interfaces
IP
Three sub-tabs — Static (static and dynamic addresses), DHCP client (pull an address from upstream), DHCP server (hand out addresses, with a live lease table)
DNS
DNS servers and cache (the app/site content filter lives under Websites & Apps)
WiFi / CAPsMAN
Wi-Fi interfaces with their configurations and security profiles; and the CAPsMAN controller — configurations, provisioning rules and remote CAPs
Services & maintenance
Tab
What you configure
PPPoE
PPPoE servers, PPP profiles, IP pools, and the RADIUS accounting interim-update interval
Hotspot
Hotspot servers, hotspot profiles and user profiles, DHCP/IP pools, and the captive-portal login page
Internet
WAN uplinks — SAMM-managed WANs and default routes, with any existing non-SAMM WANs shown read-only
Firewall
Filter 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
Update
RouterOS updates — pick an update channel, check and apply, and review installed packages
Wizard
The 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.
Welcome & detect — SAMM probes the router and shows what is
already configured, so you can skip those items in the push.
Bridge interface — name the LAN bridge.
Bridge ports — pick which physical interfaces join the bridge.
DNS — set upstream resolvers (one-click presets for Google,
Cloudflare, Quad9 and more), cache size, and optionally a DNS content filter.
NTP — set the router's clock source (NTP client, and optionally
serve time to the LAN).
Internet — add one or more WAN uplinks (Static / DHCP / PPPoE).
RADIUS to SAMM — point the router at your SAMM host for
authentication, accounting and CoA.
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.
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.
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:
The action is recorded in an audit log as a queued command.
The samm-radius service drains the queue on its next tick, applies
the change, and — if the subscriber is online — enqueues a CoA.
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.
Status
Meaning
pending
Queued, waiting for the next samm-radius tick
sent
Dispatched (transient — the send and its result are recorded in the same tick, so rows rarely stay in this state)
nack
The router rejected the CoA-Update — SAMM is retrying, then falls back to a disconnect
done
Applied successfully
failed
Gave 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.
Tile
Shows
Opens
Online now
Subscribers with a live RADIUS session right now
Users filtered to Online
Active subscribers
Active accounts, with the total subscriber count beneath
Users filtered to Active
Expired
Subscribers whose subscription lapsed with no next plan set
Users filtered to Expired
Open tickets
Support tickets not yet resolved (excludes done & closed)
Users → Support Tickets
Routers
Total NAS records, plus the count currently unreachable
The MikroTik monitor
Unpaid invoices
Invoices still needing payment follow-up
Invoices 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.
Metric
What it means
samm-radius queue
Pending 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 pending
Queued admin actions not yet applied by samm-radius
Sessions throttled
Subscribers currently held at a reduced speed by a limit — expected, not an error
Sessions snapshot
The live session count — should track Online now
Active plans
The 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
Column
Meaning
User
Username — links to the subscriber's detail page
Framed IP
The address the router assigned to this session
Router
The NAS shortname and its IP address
Plan
The subscriber's current plan
Effective speed
The 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 / Up
Live byte counters for the session
Online
How long the session has been up
Started
When 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:
List
Ranks
Top 10 download today
Largest download since the last daily reset
Top 10 upload today
Largest upload since the last daily reset
Top 10 download month
Largest download this calendar month
Top 10 upload month
Largest 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:
Figure
Meaning
Cash on hand
Total balance across all cash & bank accounts
Money you're owed
Receivables — unpaid customer and reseller invoices
Money you owe
Payables — unpaid expenses
Profit this month
Income 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:
Field
Meaning
Customer
Type-ahead search for the account being billed
Revenue category
Which income account the sale posts to
Issue / Due date
Blank issue date = today; blank due date = the issue date
Tax rate % / tax group
Defaults 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 items
One 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:
Choice
What it charges
Full invoice
Whole plan periods only — a part period rounds up to a whole one.
Segmented invoice
The 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 invoice
Change 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:
Setting
Meaning
Commission %
The agent's cut of the retail price (e.g. 40% — you keep 60% as wholesale revenue). Editable per agent, any time.
Credit limit
How far the agent's prepaid balance may go negative before renewals are refused. Set 0 for strict prepaid.
Prepaid balance
Top 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:
Report
Answers
Profit & Loss
Income vs expenses and net profit over a date range. Accrual basis — income counts when invoiced, expenses when incurred, not when cash moves.
Balance Sheet
As of a date: what you own (assets) against what you owe (liabilities) plus equity. A balanced badge confirms the two sides match.
Cash Flow
Per cash account — opening balance, money in, money out, closing balance over a range.
Aging
Outstanding receivables and payables sorted into age buckets, so you can chase overdue invoices and stay ahead of bills.
Advanced
The 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:
Refusal
What it means
That record no longer exists
The subscriber, invoice or payment was deleted after your action — there is nothing left to put back.
That record exists again
Something has been re-created in its place; undoing would overwrite the newer record.
This record changed after your action
Someone else edited it in the meantime — undoing would silently discard their edit.
That step is no longer in your history
The 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:
Direction
Examples
Behaviour
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)
Open Financial → Online payments (superadmin only).
Click a gateway to expand it — Stripe, PayPal or Binance / USDT.
Fill its fields, tick Enable this gateway, and click Save. SAMM won't let you save until the required fields are filled.
Click Run test to confirm your credentials work.
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
Create a free account at stripe.com. Keep Test mode on while you try it out.
Go to Developers → API keys and copy the Secret key (it starts with sk_).
In SAMM, expand Stripe, paste the Secret key, choose the currency and the cash account that receives it, then Save and Run test.
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
Create a PayPal Business account, then at developer.paypal.com create a REST App and copy its Client ID and Secret.
In SAMM, expand PayPal, paste the Client ID and Client secret, choose Sandbox (testing) or Live, then Save and Run test.
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.
Log in to Binance → open Account → API Management (or search "API Management").
Click Create API → choose System generated → name it e.g. "SAMM" → finish the security check.
Binance shows the API Key and the Secret Key — copy both now (the Secret is shown only once).
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.)
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
In Binance go to Wallet → Spot → Deposit (Deposit Crypto).
Choose the coin USDT.
Choose the network — TRC20 is the cheapest and most common; BEP20 and ERC20 also work. Use the same one you select in SAMM.
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
They log in to the customer portal → My invoices.
On an unpaid invoice they click Pay (or "Pay · Stripe" / "Pay · Binance" if several are enabled).
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.
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
Click Generate Keys to create the server keypair. The
Server Public Key appears once generated — clients need it.
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.
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:
State
Meaning
Running
The tunnel is active and forwarding traffic
Stopped
Configured but not currently running
Not configured
The binary is present — paste a token to set it up
Not installed
Re-run install.sh to install the cloudflared binary
It also shows the cloudflaredversion and whether the
connector is set to auto-start at boot.
Configure the tunnel
In the Cloudflare Zero Trust dashboard
(one.dash.cloudflare.com), open Networks → Tunnels
and Create a tunnel.
Choose the Cloudflared connector, name the tunnel, and save. On
the install step, copy only the token — the long string after
--token.
Paste it into SAMM and click Configure Tunnel. SAMM hands the
token to cloudflared and starts the connector.
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
Setting
Default
Controls
samm-radius interval
30 s
How often time-driven events are evaluated and CoAs sent
samm-worker interval
5 s
Router ping + MikroTik API sync cadence
Acct interim interval
60 s
The accounting interval pushed to routers
Daily reset time
00:00
When daily usage counters roll over
Server timezone
UTC
Timezone for speed windows and the daily reset
CoA default port
3799
Default UDP port for CoA packets
CoA retry max
3
Retries 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 change
Where it shows
ISP name
Invoices, receipts, hotspot cards, portal header
Support phone & email
Invoices and printed hotspot cards
Tax / registration number
Printed 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 & rate
Adds 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:
Level
Meaning
Not allowed
The area is hidden from the sidebar entirely
View
Read-only access
Edit
Full access — create, change, delete
Two rights sit beside the area levels, because each one is a money decision rather than a screen:
Right
What 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.
Control
What it does
Percentage
Positive multiplies, negative divides: +100% → double speed, −100% → half speed, −500% → a sixth of it. Speed never reaches zero.
Plans to boost
Tick any number of plans; each row shows the plan rate, the boost in force and the effective speed right now.
Revert automatically after
Hours 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.
Tier
AAA users
Hotspot cards
NAS / routers
Unregistered
25
200
1
Free
100
500
2
Plus
500
2,000
3
Pro
2,000
5,000
5
Pro Max
unlimited
unlimited
unlimited
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
Open System → License.
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.
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:
Stage
What happens
Warning
A reminder banner; everything keeps running
Grace
A short window to reactivate; subscribers stay online
Soft lockdown
Background services stop; RADIUS keeps authenticating for about 7 days
Hard lockdown
Services 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:
Page
What the subscriber sees
Overview
Account status, plan, expiry, today's and this month's usage, any outstanding invoice
Usage & sessions
Total downloaded/uploaded, uptime budget, and full session history
My plans
The current plan plus the catalogue of available plans
My invoices
Billing history with one-click PDF download
Support tickets
Open and follow support tickets
Profile
Edit 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:
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
Area
Endpoints
Scope
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}
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:
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
File
Holds
/etc/samm/samm.yaml
The database DSN, connection-pool sizes, log level
/etc/samm/api.env
Portal session secrets and the password-recovery SMTP settings
/etc/samm/secret.key
The 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 lossThis 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.