The gateway is installed on your server. Your SMS, your contacts, your conversations and your logs are stored there and nowhere else: we have no copy, no access and no way to read them. That also means part of the security is in your hands: the machine, its network, its updates and its backups.
This page explains what the gateway does to protect your data, which settings affect it, and what you should check yourself.
Your data stays on your server
| Data | Where it lives | Leaves your server? |
|---|---|---|
| SMS sent and received, conversations | The gateway's database, on your machine | Only towards your phones, which send and receive them |
| Contacts, groups, templates, rules, campaigns | Same database | Never |
| Activity log and technical logs | Same database, and the gateway's own output | Never |
| Webhook notifications | Sent by the gateway | Only to the addresses you configured, and without SMS text or full number |
| Alerts (Settings, Notifications) | Sent by the gateway | By SMS through your SIMs, by e-mail through your SMTP server, and to the push service of the browsers your users subscribed. Never an SMS text nor a full number |
| Licence information | Sent by the gateway | To our licence server, limited to what is listed below |
The gateway makes only a few kinds of outgoing connections on its own: to our licence server, to the webhook addresses you created, and, if you switch the alerts on, to your SMTP server and to the push service of the subscribed browsers. Everything else is incoming: your browser, your phones and your applications connect to it. The API reference and the dashboard load nothing from the internet.
How the gateway protects your data
Accounts and sign-in
- Passwords are stored as a salted, deliberately slow fingerprint (argon2id), never in clear text. They need at least 12 characters, with no composition rule: a long sentence is stronger than a short word with a symbol.
- Brute force. After 5 failed sign-ins for the same address or the same account, sign-in is locked for 30 seconds, then twice as long after each further failure, up to 15 minutes. A wrong email and a wrong password get the same answer, so no one can test which accounts exist.
- The first account can only be created with the setup code shown at the end of the
installation (
sms-gateway setup-codeshows it again). A bot that finds your gateway on the internet before you cannot create the administrator account in your place. - Changing your email or password asks for the current password. Changing the password signs out every other session of the account.
Sessions
The dashboard keeps you signed in with a cookie that scripts cannot read, valid for 7 days and extended while you use it. Signing out ends the session immediately on the server. Disabling an account or resetting its password ends all its sessions at once. Every change made from the dashboard is protected against forged requests from other websites.
Roles
Each dashboard account has one of three roles, set in Settings > Users and roles:
| Role | What it can do |
|---|---|
| Superadmin | Everything, including accounts, licence, settings, API keys, backups, phone pairing and routing rules |
| Operator | Send, reply, and manage contacts, templates, rules, campaigns and webhooks. No accounts, settings, keys or backups |
| Read only | See everything, change nothing |
The role is checked by the gateway on every request, not only hidden in the interface. The last active superadmin cannot be demoted, disabled or deleted, so the installation always keeps an administrator. Give the superadmin role to as few people as possible. See Users and roles.
API keys
Applications use API keys, never a dashboard account. Each key has a scope (read, send,
admin), an optional list of allowed addresses and optional limits per minute and per day. Only a
fingerprint of the key is kept, so a copy of the database does not reveal it. Revocation is
immediate. See API keys.
Phones
- A phone is paired by scanning a QR code that is valid for 5 minutes and usable once. A QR code caught in a screenshot is useless afterwards. The manual code offered to phones without a camera follows the same rules, and repeated wrong codes are blocked.
- Each phone receives its own secret at pairing. Every message exchanged between the phone and the gateway is signed with it and dated, so a message captured on the network cannot be replayed.
- Unpairing a phone from the Devices page cuts its connection at once.
- The dashboard shows the SHA-256 fingerprint of the Android app it offers for download, so you can compare it with the one given in your customer area.
Secrets stored by the gateway
Some secrets must be readable again by the gateway: the phones' secrets, the webhook secrets and your
licence key. They are encrypted (AES-256-GCM) with a master key that is kept outside the
database, in the file secret.key of the data directory (or in GATEWAY_SECRET_KEY if you set it).
A copy of the database alone, a backup for example, therefore does not reveal them.
Everything that only needs to be recognised is kept as a fingerprint that cannot be reversed: passwords, sessions, API keys, pairing codes.
The master key is precious. Without it, a restored database loses its phones (to pair again), its webhook secrets and its licence key. Back it up, separately from the database backups: see Backups.
Webhooks
Every webhook call is signed with a secret that only you and the gateway know, and dated, so your application can refuse a forged or replayed call. It carries identifiers, never the text of an SMS or a full number. The gateway refuses to call its own machine or cloud metadata addresses. See Webhooks.
Alerts
Alerts carry a short text only: the phone as you named it, the SIM by its slot, counts. Never the text of an SMS, never a full phone number. Changing where they go is reserved for a superadmin.
- E-mail goes through the SMTP server you configure. Its password is encrypted like the other secrets and never shown again. With the security set to None, the gateway refuses to send the password to a server that is not on the same machine: choose STARTTLS or TLS for a remote server.
- Browser notifications (Web Push) travel through the push service of the browser vendor (Google for Chrome and Edge, Mozilla for Firefox, Apple for Safari): that is how a browser receives a notification while the page is closed. Each message is encrypted end to end between your gateway and the browser; the vendor relays bytes it cannot read, and only learns that a notification was sent to that browser. The gateway identifies itself with a key pair generated on your server the first time it is needed; the private half is stored encrypted and never leaves it. The gateway refuses push addresses that point to its own machine or local network.
- Each user manages the browsers they subscribed, and can unsubscribe one from Settings, Notifications. A deleted account loses its subscriptions.
Logs
Neither the technical logs nor the Activity log ever contain the text of an SMS, a full phone
number (they show +261******89), a key, a token or a password. Search terms and numbers typed in
URLs are hidden before a request is logged. The HTTPS front end installed with the gateway also
strips keys and cookies from its access log. The technical view of the logs is reserved for
superadmins.
The connection
- With a domain name, the installer puts an HTTPS server (Caddy) in front of the gateway, with a free certificate renewed automatically. The gateway itself only listens on the machine's internal address, and is not reachable from outside without HTTPS.
- The gateway refuses to start with a public
http://address: over plain HTTP on the internet, passwords and sessions would cross the network in clear text. - The container runs with a read-only file system, without privileges, and only writes to its data directory.
Settings that affect security
| Option | Where | Default | Effect |
|---|---|---|---|
Installation mode --domain or --lan |
Installer | asked at installation | --domain: HTTPS with a certificate, gateway reachable only through it. --lan: plain HTTP on your local network. See below |
GATEWAY_PUBLIC_URL |
.env of the installation |
set by the installer | The address users and phones use. Must be https://, unless it is a local name (.local, localhost) |
GATEWAY_INSECURE_COOKIES |
.env |
false (domain), true (local network) |
true lets the browser keep your session over plain HTTP. The session then crosses the local network unencrypted. Changes nothing else |
GATEWAY_SECRET_KEY |
.env |
empty: secret.key is drawn at first start |
The master key that encrypts stored secrets. Changing it makes everything encrypted with the old one unreadable |
GATEWAY_TRUSTED_PROXIES |
.env |
the address of the built-in HTTPS server | Which proxies may report the visitor's real address. The address is used by sign-in locks, API key address lists and limits. Too wide a value lets anyone pretend to be any address |
GATEWAY_WEBHOOKS_ALLOW_PRIVATE_NETWORKS |
.env |
true |
false forbids webhooks towards your private network, leaving only public addresses |
GATEWAY_LOG_RETENTION_DAYS |
.env |
30 |
How long the Activity log is kept (sign-ins, key changes, failures). Longer helps an investigation, shorter keeps less history |
GATEWAY_LOG_LEVEL |
.env |
info |
Detail of the technical logs. No level ever writes SMS text or a full number |
| Roles of each account | Settings > Users and roles | the role chosen at creation | What each person can do. See Roles |
| Scope, allowed addresses, limits of a key | System > API keys | Read, any address, no limit | What each application can do, from where and how often |
| Webhook secret and destination | Webhooks page, API | secret drawn by the gateway | Who receives notifications and how they prove their origin |
All the environment variables are described in the
installation guide. A variable is changed in the .env file
of the installation, then applied by restarting the gateway.
Domain or local network
| Mode | Address | Encryption | For whom |
|---|---|---|---|
--domain (recommended) |
https://sms.example.com |
HTTPS end to end | Any installation reachable from the internet, or used from outside |
--lan |
http://<machine>.local:8080 |
None: passwords and sessions travel in clear text on the local network | A closed network you trust entirely (office, home), with no access from outside |
Never make a --lan installation reachable from the internet (port forwarding on your router, for
example). If you need access from outside, reinstall in --domain mode.
What you should do
A checklist to go through after installation, then from time to time.
At installation
- Install in
--domainmode as soon as the gateway is used outside a closed local network. - Create the first account right after installation, with the setup code, and a password of at least 12 characters that you use nowhere else.
- Copy
secret.keysomewhere safe, away from the server (see Backups).
The server
- Firewall: in domain mode, open only ports 80 and 443 (plus SSH for you, ideally limited to your address). The gateway's port 8080 must not be reachable from outside. In local network mode, open 8080 on the local network only.
- Apply the system's security updates, and update the gateway when a new version is published.
- Keep the server's clock on time (NTP): the signatures of phones and webhooks depend on it.
- Limit who has administrator access to the machine: whoever is
rooton the server can read everything, whatever the gateway does.
Accounts and keys
- One account per person, never shared. The Read only role for those who only consult.
- As few superadmins as possible, at least two if you want a replacement.
- Disable the account of someone who leaves: their sessions end at once.
- One API key per application, with the narrowest scope, allowed addresses when possible and a daily limit.
- Revoke the keys nobody uses (column Last used of API keys).
Phones
- Lock the phones with a code and keep them in a place only your team can access: whoever holds a paired phone can read the SMS it receives.
- Unpair a phone that is lost, replaced or sold, from the Devices page.
Backups
- Enable scheduled backups and copy them off the server regularly.
- Protect the copies: a backup contains all your data (messages, contacts, accounts), without encryption. Store it encrypted, or in a place with restricted access.
- Test a restore from time to time.
Watch
- Read the Activity log now and then: sign-ins, failed sign-ins, key creations and revocations, phones going offline.
- Subscribe to
device.offlineandbackup.failedby webhook if you want to be alerted.
What our licence server receives
The gateway contacts our licence server to activate your licence, then about once a day to renew it. Each contact sends exactly this, and nothing else:
| Information | What it is |
|---|---|
| The licence key | Sent over HTTPS so that we can check it. Our server only stores a fingerprint of it |
| The version line | The major version of the gateway, to check that the key is valid for it |
| The exact version | The build number of your gateway |
| The machine fingerprint | A fingerprint computed on your server. The information it is computed from never leaves |
| The number of phones | How many phones are paired |
| A counter | A number that only increases, to detect a clock moved backwards |
No phone number, no message, no contact, no name, no account email and no log is ever sent: the request has no field for them. Our answer is a licence token signed by us, which your gateway verifies with a public key built into it.
If our servers are down
Nothing stops. Your gateway does not depend on us to send or receive a single SMS.
- An unreachable licence server, a timeout, an error page or an unsigned answer are all treated as "our side is down", and never as a problem with your licence. The dashboard shows an information notice, and the gateway keeps trying: after 15 minutes, 1 hour, 6 hours, then once a day.
- A licence stays valid 90 days after its last renewal. Beyond that, a banner appears for 30 days, then a lasting warning: sending is never cut because our server did not answer.
- A licence held for 12 months or more works with no time limit, whether our server answers or not.
- Only an explicit withdrawal of your licence, signed by us and verified by your gateway, can restrict it. Even then, you keep reading and exporting all your data: only new changes are refused.
The details, and what to do in each situation, are in Licence.
Known limits
We prefer to tell you what the gateway does not do yet:
| Subject | Today |
|---|---|
| Two-factor authentication | Not available. Use long, unique passwords and limit the number of superadmins |
| Encryption of the database | The database file is not encrypted on disk. It is protected by the server's permissions, and the secrets inside are encrypted separately. Use disk encryption on the server if you need it |
| Encryption of backups | Backups are not encrypted. Protect the copies yourself |
| Local network mode | Plain HTTP: suitable only for a network you trust |
| Changing the master key | No automatic procedure: changing it makes the stored secrets unreadable (phones to pair again, webhook secrets to set again, licence key to enter again) |