Ir al contenido principal

Backup and restore

Protect your installation: the three ways to save your data, what each one contains, how to get copies off the machine, how to restore, how to export your data, and how to check that a backup is worth something.

Everything your gateway knows (messages, contacts, conversations, campaigns, rules, settings, accounts, paired phones) lives on your machine, and nowhere else: we keep no copy. Losing the disk without a backup means losing all of it. This page explains how to protect yourself.

Automatic backup is on by default: every day at 03:00 in the platform time zone, seven copies kept, on new installations and on installations updated from an earlier version alike. Check it, and change it, in Settings > Backup and export (see Automatic backup). These copies stay on the machine they protect: on the day you install, also decide how you keep copies off the machine.

The three tools, and what each is for

Tool What it produces Contains the master key Interrupts sending Best for
sms-gateway backup (command line) An archive of the whole data folder (.tar.gz) Yes A few seconds Disaster recovery, moving to another machine
Automatic backup and Back up now (dashboard or API) A copy of the database (.db), kept on the machine No No Daily restore points, a copy before a risky change, restoring from the dashboard
Full export (dashboard or API) The database, or messages, contacts and conversations as CSV or JSON No No Taking your data to another tool, spreadsheets, archiving

The master key (secret.key) protects the secrets of your paired phones, the webhook secrets and your stored license key. A database restored without its master key opens normally, but:

  • every phone must be paired again;
  • every webhook secret, and the secret of every rule action that calls a URL, must be set again (and updated on the receiving side);
  • the license key must be entered again.

That is why the sms-gateway backup archive, which contains the key, is the one to keep for a disaster. The key is kept out of the database on purpose: a database copy that leaks does not hand over your phones.

Who can do what

Action Dashboard API key scope
See, create, download, restore backups Superadministrator only admin
Export the full database Superadministrator only admin
Export messages, contacts, conversations Every role admin
sms-gateway backup - root on the machine

Backups and the database export contain the accounts of the dashboard, which is why they are reserved to the superadministrator. Other roles see only the Full export part of the screen.

Make a backup

From the dashboard

Settings > Backup and export > Back up now. The gateway writes a consistent copy of the database without interrupting sending, reads it back to make sure it is valid, and only then counts it as successful. The new copy appears in Available backups, and the attempt in Backup log.

If the copy fails (most often: the disk is full), the attempt shows as Failed in Backup log with a short reason, and the damaged file is deleted.

From the command line

On the machine, from the folder where you want the archive:

sudo sms-gateway backup
Point Behavior
What is copied The whole data folder: database, master key, and the backups made from the dashboard
Where it is written The current folder, as sms-gateway-backup-<YYYYMMDD-HHMMSS>.tar.gz, readable by root only
Interruption The gateway stops for the time of the copy (seconds for a normal database), then restarts; the command returns once the gateway answers again. Phones keep their messages meanwhile
Options None
Old archives Never deleted by the command: clean up yourself

On Windows, there is no sms-gateway command. From %ProgramData%\SmsGateway, in PowerShell:

docker compose stop gateway
docker run --rm -v sms-gateway_gateway-data:/data:ro -v "${PWD}:/out" alpine:3 tar czf /out/sms-gateway-backup.tar.gz -C /data .
docker compose start gateway

Never copy the database file by hand while the gateway runs. A copy taken in the middle of a write gives a damaged file, and you only find out on the day you need it. Use one of the tools above.

Automatic backup

The gateway backs up its database on its own, without interrupting sending, and reads every copy back before counting it as successful. The copies appear in Available backups with the origin Scheduled, and every attempt in Backup log.

Set it in Settings > Backup and export, Scheduled backup card (Superadmin only), then Save. The change applies within a minute, without a restart.

Setting Default Possible values Effect
Automatic backup On On, off Off: only the backups you make yourself exist. Back up now works either way
Frequency Once a day Once a day, every N hours How the backups are spaced
Time 03:00 Any time, HH:MM Once a day: when the backup runs, in the platform time zone (Settings > Sending)
Every (hours) 24 1 to 168 (one week) Every N hours: hours between two automatic backups
Copies kept 7 1 to 365 See How many dashboard backups are kept

Good to know:

  • Daylight saving time is followed: 03:00 stays 03:00 local time on both sides of the change. A time that does not exist on the day of the change (inside the skipped hour) runs once, just after it; a time that occurs twice runs once.
  • A gateway that was stopped at the due time makes the missed backup once when it starts again, not one per missed day. A fresh installation, or one that never made an automatic backup, makes its first one within a minute.
  • A manual backup does not move the schedule: the nightly backup still runs after a Back up now at 02:59.
  • One backup at a time: an automatic backup that falls while another backup is being written waits for the next minute.
  • Every N hours counts from the previous automatic backup, failed or not: a full disk is retried once per interval, not every minute.

The Next backup box shows when the next one is due, in the platform time zone: None when the automatic backup is off, On the next pass when it is due within the minute.

Through the API, with an API key of scope admin: PATCH /api/v1/settings with a backup block (enabled, frequency daily or interval, dailyAt HH:MM, intervalHours, retention). An omitted field is left as it is.

curl -X PATCH https://sms.example.com/api/v1/settings \
  -H "X-API-KEY: sk_..." -H "Content-Type: application/json" \
  -d '{"backup": {"frequency": "daily", "dailyAt": "02:30", "retention": 14}}'

The command-line archive is not scheduled by the gateway. Run sudo sms-gateway backup when you want the full archive with the master key: after installing, before an update or a move, and regularly if you keep it off the machine.

Keep copies off the machine

A backup that stays on the disk it protects does not survive the loss of that disk, and one that stays in the same building does not survive a fire or a theft.

  • Download a dashboard backup (automatic or manual): in Available backups, the download button next to each file. Through the API: GET /api/v1/backups/{name}/download.
  • Copy the sms-gateway backup archives to another server or to storage of your choice (scp, rsync, your provider's object storage).

Three rules:

  1. Encrypt the copies. Backups are not encrypted: they contain every message, every contact and every phone number in clear, and the command-line archive also contains the master key.
  2. Keep the master key, or the full archive that contains it, even if you rely on dashboard backups.
  3. Delete old copies you no longer need, on both sides.

How many dashboard backups are kept

The Copies kept value of the Scheduled backup card (7 by default, from 1 to 365) applies to Available backups, automatic and manual copies together. After each successful backup, the oldest copies beyond that number are deleted. Never before, and never after a failure: a failed backup never costs you an older good one. Lowering the value deletes the surplus at the next successful backup, not at once.

Disk space: each copy is about the size of the database. Seven copies of a database of 200 MB take about 1.4 GB in the data folder.

A file you add yourself counts too. Any .db file placed in the backups folder is listed as restorable and counts towards the copies kept. Keep your own original elsewhere: do not rely on that folder as your only copy.

Restore a dashboard backup

A restore replaces the whole database with the chosen copy. Everything written since that copy (messages, contacts, settings, accounts) disappears from the database in use.

  1. Settings > Backup and export > Available backups, the restore button on the chosen line.
  2. Read the confirmation, tick I understand that the data written since this backup will be lost, then Prepare the restore. The gateway checks the file and prepares it; nothing is replaced yet.
  3. A Restore pending banner appears, with Cancel the restore if it is not the right copy. Preparing another copy replaces the pending one.
  4. Restart the gateway to apply it: sudo sms-gateway restart (on Windows, docker compose restart gateway from the installation folder).
  5. Sign in again, and check your data.

Why a restart: the database cannot be swapped while the gateway uses it. The swap happens at the next start, before anything else, and only if the prepared file is exactly the one that was checked.

The gateway refuses a copy in two cases, each with a precise message:

Refusal Meaning What to do
BACKUP_UNREADABLE The file is damaged, or is not a backup of this product Take another copy
BACKUP_SCHEMA_TOO_RECENT The copy was made by a newer version of the gateway Update the gateway (sms-gateway update), then try again

A copy made by an older version is accepted: it is brought up to date automatically at the restart.

A failed restore never prevents the gateway from starting: it starts on the database it had, and the logs (sms-gateway logs) say why.

The previous database is kept

The database that was in use is not deleted: it is set aside in the data folder as gateway.db.pre-restore-<timestamp>. It is your way back if the restored state does not suit you, and it is never deleted automatically: remove it yourself once you are satisfied, especially on a large database, or it will eventually fill the disk.

To go back to it, with the gateway stopped:

sudo sms-gateway stop
# Find the exact name of the set-aside file
docker run --rm -v sms-gateway_gateway-data:/data alpine:3 ls -la /data
# Put the previous database back, keeping the restored one aside
docker run --rm -v sms-gateway_gateway-data:/data alpine:3 sh -c '
  mv /data/gateway.db /data/gateway.db.restore-rejected &&
  rm -f /data/gateway.db-wal /data/gateway.db-shm &&
  mv /data/gateway.db.pre-restore-1756800000 /data/gateway.db'
sudo sms-gateway start

Replace 1756800000 with the value shown by ls. The -wal and -shm files belong to the database being set aside: they must be removed, otherwise they would damage the one you put back.

Restore a copy made on another machine

A backup downloaded earlier, or taken from another installation, can be restored the same way once it is in the backups folder of this gateway:

# Click "Back up now" once first, so that the backups folder exists
docker run --rm -v sms-gateway_gateway-data:/data -v "$PWD:/in" alpine:3 sh -c '
  cp /in/gateway-20260901T020000Z-01930f2c.db /data/backups/ &&
  chown 65532:65532 /data/backups/gateway-20260901T020000Z-01930f2c.db'

The file appears in Available backups with the origin Imported. Its name must end in .db, start with a letter or a digit, and contain only letters, digits, dots, dashes and underscores. Then follow Restore a dashboard backup.

Remember: this copy does not carry the master key of its original machine. If this gateway does not have the same secret.key, phones must be paired again and the license key entered again.

Restore a full archive (sms-gateway backup)

This brings back the whole installation as it was, master key included: phones reconnect without pairing, and the license needs nothing. It replaces everything currently in the data folder.

sudo sms-gateway stop
docker run --rm -v sms-gateway_gateway-data:/data -v "$PWD:/in" alpine:3 sh -c '
  rm -rf /data/* &&
  tar xzf /in/sms-gateway-backup-20260901-023000.tar.gz -C /data'
sudo sms-gateway start

The gateway must be at least the version that made the archive: update it first if needed. On a new machine, install the gateway first, then run these commands (see Migrating to another server).

Export your data

Settings > Backup and export > Full export. Exports are not backups: they let you take your data elsewhere, in open formats that any tool reads.

Export Content Formats API
Full database A fresh copy of the whole database, accounts included, opened by any SQLite tool SQLite GET /api/v1/export/database
Messages The whole history, texts included CSV (default), JSON GET /api/v1/export/messages?format=csv
Contacts The directory as stored, with labels and opt-outs CSV (default), JSON GET /api/v1/export/contacts?format=json
Conversations The threads, without the texts (they are in the messages export) CSV (default), JSON GET /api/v1/export/conversations

The columns, in order:

  • Messages: id, conversationId, direction, phone, body, encoding, segments, status, errorCode, deviceId, simSlot, attempts, createdAt, sentAt, deliveredAt, failedAt
  • Contacts: id, phone, firstName, lastName, company, email, notes, tags, blacklisted, createdAt, updatedAt
  • Conversations: id, phone, contactId, state, unreadCount, pinned, archived, assignedTo, createdAt, lastMessageAt

Good to know:

  • Rows go from the oldest to the newest. An empty export still has its header line (CSV) or [] (JSON). A missing date is an empty field, never a fake date.
  • These files contain message texts and full phone numbers: store them accordingly.
  • Exports stay available even if your license is withdrawn: your data remains yours.
  • The full database export needs temporary space on the machine, about the size of the database. If it fails on a very large database, make a backup and download it instead.

Be warned when backups fail

A gateway that has stopped backing up looks exactly like one that works. Two ways to find out:

  • Backup log in Settings > Backup and export lists every attempt, failures included, with a short reason (for example snapshot could not be written: most often a full disk). A failure is also written, as an error, in the Activity log.
  • Notifications: the Backup failed alert (Settings > Notifications) is on by default and sends a message on every channel you configured (SMS, e-mail, browser) as soon as an automatic or manual backup fails. See Settings, notifications.
  • Webhooks: subscribe a webhook to the backup.failed event (and backup.completed if you want a positive signal) to be alerted by your own tools. See Webhooks.

Check that a backup is worth something

A backup nobody ever restored is a hope, not a backup. The gateway already reads back every copy it makes, which proves the file is a valid database. It does not prove that you know how to bring it back.

In one minute, on a downloaded copy, with the sqlite3 tool:

sqlite3 gateway-20260901T020000Z-01930f2c.db 'PRAGMA quick_check;'
# must answer: ok
sqlite3 gateway-20260901T020000Z-01930f2c.db 'SELECT count(*) FROM messages; SELECT count(*) FROM contacts;'
# plausible numbers

The real test: restore a full archive on a spare machine (a small VPS, a virtual machine), following Restore a full archive, sign in with your usual account and check that your conversations are there. Do it on a machine that phones do not know: paired phones only connect to the address of your real gateway, so the test copy does not disturb them. Delete the test machine afterwards: it contains all your data.

Do this test after each important update, after any change to your backup routine, and at least once before you need it.

API reference

All these operations need an API key of scope admin (header X-API-KEY) or a superadministrator session. Details in the API reference.

Operation Endpoint Answer
Make a backup now POST /api/v1/backups 201 with the attempt, 503 if it failed
List available backups GET /api/v1/backups Newest first; journalled: false for an imported file
Backup log GET /api/v1/backups/attempts Every attempt, failures included
Schedule in effect GET /api/v1/backups/schedule enabled, frequency, dailyAt, timezone, intervalSeconds, retention, lastAttemptAt, nextRunAt
Change the schedule PATCH /api/v1/settings with a backup block The settings in force, backup included; 422 on a value out of range
Download a backup GET /api/v1/backups/{name}/download The .db file
Prepare a restore POST /api/v1/backups/{name}/restore 202 with restartRequired: true; 404, or 422 with BACKUP_UNREADABLE / BACKUP_SCHEMA_TOO_RECENT
See the pending restore GET /api/v1/backups/restore {"pending":true,"name":"..."} or {"pending":false}
Cancel the pending restore DELETE /api/v1/backups/restore 204
Exports GET /api/v1/export/{database,messages,contacts,conversations} The file

A backup is refused while the license is withdrawn (it is a write); downloads and exports keep working.

Current limits

  • No encryption and no automatic upload of backups: copying them elsewhere and encrypting them is up to you.
  • No upload of a backup file from the dashboard: a copy from elsewhere is placed in the backups folder with the command shown above.
  • The gateway.db.pre-restore-... files are never deleted automatically.

Buscar en la documentación

Escriba algunas palabras y elija una página.