Skip to content

Backups & Recovery

ProxPanel backs up your entire Postgres database — subscribers, services, RADIUS check/reply, accounting records, transactions, invoices, settings — into a single encrypted file. There is no “config only” vs “full” split that matters for recovery; the encrypted .proisp.bak is what restores a server to working state.

Backups can be created manually from the UI, scheduled hourly/daily/weekly/monthly, and pushed to FTP or the ProxRad cloud-backup service. The file itself is AES-256-GCM encrypted with a key derived from your license, so it survives leaving your server without leaking subscriber data.

Backups in the sidebar (admin only). The page has two tabs:

  • Backups — list of files in /var/backups/proisp/, with Download, Restore, Delete actions.
  • Schedules — cron-style rules for automated backups.
proisp_full_20260512_140530.proisp.bak ← Postgres dump, AES-256-GCM
proisp_data_20260512_140530.proisp.bak ← (legacy) subscriber tables only
proisp_config_20260512_140530.proisp.bak ← (legacy) settings/users only
mikrotik_RouterName_20260512_140530.tar.gz ← RouterOS /export from MikroTik

Every .proisp.bak file starts with one of two magic headers:

HeaderVersionCross-server restore
PROXPANEL_ENCRYPTED_BACKUP_V1\nLegacy (≤ v1.0.207)Requires manually entering source license key on restore
PROXPANEL_ENCRYPTED_BACKUP_V2\nLICENSE_KEY=PROXP-XXXXX-…\nCurrent (v1.0.208+)Fully automatic — license key embedded in header

After the header, the rest of the file is AES-256-GCM ciphertext of a pg_dump -Fc (Postgres custom format, compressed binary). For the encryption-key derivation and cross-server flow, see Cross-Server Restore.

key = SHA-256("ProxPanel-Backup-Encryption-2024" || DB_PASSWORD)

The DB password is fetched from the license server on startup (see Secrets storage on the license server). This means:

  • The same panel always re-derives the same key — restoring on the same server “just works”.
  • A cloned /var/backups directory is useless without the license key. An attacker who steals the file but not the license cannot decrypt it.
  • Cross-server restore works because the V2 header includes the source license key; the destination panel can ask the license server for the source’s DB password.
  1. Click Backups in the sidebar.

  2. Click Create Backup (top right). Confirm “Full backup” in the modal.

  3. Wait 5–60 seconds depending on database size. The page refreshes when done.

  4. The new file appears at the top of the list with size, timestamp, and an [encrypted] badge.

Internally, this runs:

pg_dump -h db -U proxpanel -d proxpanel -Fc \
--exclude-table-data=radius_logs \
--exclude-table-data=radpostauth \
--exclude-table-data=cpe_tasks \
-f /var/backups/proisp/.temp_full_TIMESTAMP.dump

Then encrypts that temp file into the final .proisp.bak. The three excluded tables auto-prune to 30 days anyway — they’re noisy and re-populate from live RADIUS traffic, so they’d bloat the backup for zero recovery value.

Backups → Schedules → New Schedule.

FieldNotes
NameFree-form, shown in logs.
Frequencyhourly / daily / weekly / monthly.
Day of week / Day of monthFor weekly / monthly.
Time of dayHH:MM in your configured system timezone (Settings → System → Timezone).
RetentionDays to keep. Files older than this are deleted on each scheduler tick.
Storagelocal only / local + ftp / local + cloud.

The scheduler runs every 60 seconds (services/backup_scheduler.go) and picks up due schedules with a ±2 minute window so a brief API restart at 02:00 doesn’t miss the 02:00 schedule. A same-day deduplication check prevents two runs of the same schedule on the same day.

Host: backup.example.com Port: 21
Username: backupuser Password: ********
Path: /proxpanel-backups/
Passive: yes TLS (FTPS): optional

On every run, the encrypted backup is created locally, then uploaded to the FTP server. Local copy is retained per the retention setting.

Cloud is the ProxRad-managed backup service:

  • Endpoint: https://license.proxrad.com/api/v1/cloud-backup/upload
  • Authenticated with the panel’s license key.
  • Encrypted file uploaded as-is; the license server stores it in object storage without ever holding the decryption key.
  • Retention on the cloud side: 30 days (configurable by support).

This is the recommended off-server option for customers without their own FTP infrastructure.

Local backups live in /var/backups/proisp/ on the host (bind-mounted into the API container). A 30 K-subscriber panel produces ~80–120 MB compressed per full backup; a daily backup with 30-day retention costs roughly 3 GB on disk.

The scheduler deletes files older than retention days at the end of each successful run. Manual backups are also subject to retention if they match the schedule’s filename prefix.

Same-server restore (most common)

  1. Backups page → find the file → click Restore.

  2. Confirm “This will overwrite the current database” in the modal. The destination license key field can be left empty — the system auto-detects from the V2 header.

  3. The API container stops accepting writes during restore (~30 s – 5 min depending on size).

  4. When the page returns “Restored successfully”, refresh — your data is now whatever it was at the time of the backup.

V1 backup (legacy)

Backups created before v1.0.208 don’t embed the license key in the header. On restore:

  1. Open the Restore modal.
  2. Manually enter the Source License Key of the panel that created the backup.
  3. The system fetches that license’s DB password from the license server and uses it to decrypt.

If you don’t know the source license key, contact info@proxrad.com with the file timestamp — support can look it up from the upload logs if it was a cloud backup.

Different server (cross-server restore)

This is the migration / disaster-recovery path. The destination server’s license key is automatically replaced with the source’s during restore. See the dedicated Cross-Server Restore page.

When SAAS_MODE=true, backups are per-tenant:

  • Scheduler iterates admin.tenants and runs each tenant’s schedules in its own schema (tenant_xxx.backup_schedules).
  • Each backup file is named tenant_xxx_full_TIMESTAMP.proisp.bak and contains only that tenant’s schema, dumped with pg_dump --schema=tenant_xxx.
  • Cloud uploads include the tenant ID in the metadata so the SaaS admin UI can list per-tenant backups.
  • A tenant restoring “their” backup overwrites only their schema, never the global admin.* tables.

Tenants cannot see other tenants’ backups in their UI. The platform admin (super-admin) can see all of them via the admin panel.

The MikroTik Backup button (top of the Backups page) connects to a NAS over the RouterOS API and runs:

/export file=proxpanel-backup-TIMESTAMP
/file fetch

The exported config is pulled to /var/backups/proisp/mikrotik_RouterName_TIMESTAMP.tar.gz. This is a plain MikroTik config dump, not encrypted (RouterOS exports already redact API passwords and user passwords with 0x...).

Use it to capture interface configs, queue trees, firewall rules, and IP pools so you can rebuild a router from scratch after hardware failure.

Terminal window
# List backups on the host
ls -lah /var/backups/proisp/
# Inspect the magic header of a backup
head -c 60 /var/backups/proisp/proisp_full_20260512_140530.proisp.bak
# → PROXPANEL_ENCRYPTED_BACKUP_V2
# → LICENSE_KEY=PROXP-XXXXX-XXXXX-XXXXX-XXXXX
# → <binary ciphertext>
# Tail the scheduler log
docker logs proxpanel-api 2>&1 | grep BackupScheduler
# Trigger a manual backup via API
curl -s -X POST -H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"type":"full"}' \
http://localhost/api/backups | jq
  • “Failed to decrypt backup” on same server. DB password changed between backup creation and restore — usually because the panel was reinstalled. Restore using the source license key (cross-server flow).
  • pg_dump: error: server version: 16.X; pg_dump version: 14.X. The API container uses the wrong Postgres client. The install script pins postgresql-client-16 — if you skipped that step, run docker exec proxpanel-api apt-get install -y postgresql-client-16 and restart the container.
  • Backups appear in the UI but not in /var/backups/proisp/. The bind-mount is broken. Check docker inspect proxpanel-api | grep -A 3 Mounts shows /var/backups/proisp mapped to a host directory.
  • Scheduler skips runs. Check the configured timezone — system_preferences.system_timezone must be a valid Go timezone like Europe/Berlin, not just CET. Without tzdata in the API container the scheduler falls back to UTC and runs everything 0–12 hours off.
  • Cloud upload fails with 401. License key changed (re-activation, hardware migration). Re-validate the license from Settings → License, then trigger a manual scheduled-backup run.
  • backups.view — see the Backups page.
  • backups.create — create manual backups.
  • backups.restore — restore a backup (destructive).
  • backups.delete — remove backup files.
  • backups.edit — manage schedules.

Resellers can be granted these permissions individually. Most operators give resellers backups.view only and keep restore/delete admin-only.

  • Cross-Server Restore — the V2 auto-detect flow in detail.
  • Updates — pre-update backup is taken automatically and used for rollback on failure.
  • HA Cluster — clustered deployments still need application backups; streaming replication doesn’t protect you from DROP TABLE.