I migrated voicemail from FreePBX to FS PBX for two domains and ended up with a small interactive tool, so I'm sharing it in case it saves someone the work. It imported about 1,070 messages across two domains on an HA pair (primary + standby, PostgreSQL logical replication + Syncthing), and the messages played fine from the web UI and from *97.
TAKE IT OR LEAVE IT: this is shared as-is, under the MIT license, with no warranty and no support. I'm not planning to develop it further. The code is public, so fork it and change whatever your setup needs. It writes directly to the database and the storage folder, so back up and test on a copy first.
What it does
TAKE IT OR LEAVE IT: this is shared as-is, under the MIT license, with no warranty and no support. I'm not planning to develop it further. The code is public, so fork it and change whatever your setup needs. It writes directly to the database and the storage folder, so back up and test on a copy first.
What it does
- Reads a copy of /var/spool/asterisk/voicemail/default from FreePBX (one folder per mailbox). A tar.gz or an unpacked folder both work.
- Adds one row per message to v_voicemail_messages and copies the audio to /var/lib/freeswitch/storage/voicemail/default/<domain>/<ext>/msg_<uuid>.wav (owned by www-data). If the domain uses base64 storage it also fills message_base64. Detected automatically.
- Asterisk's uppercase .WAV files are GSM-in-WAV. These are converted to plain 8 kHz 16-bit PCM (needs ffmpeg or sox).
- INBOX/Urgent become new messages; Old and any custom folders you choose become saved messages.
- Finds the database login itself (local postgres account, then DB_PASSWORD from /var/www/fspbx/.env, and only then asks). Passwords are never printed or logged.
- Menu: setup, read-only pre-flight checks, dry run, test one mailbox, full import, verify, undo, logs, clean up. Every write is previewed first and needs confirmation.
- Safe to re-run with a newer copy before cutover: messages are matched by mailbox + original time + caller number + length (not file name, because Asterisk renumbers msg0000.. when messages move or are deleted), so only new messages are imported.
- Undo removes exactly the rows and files a given import added.
- Back up first, and try it on a test domain or mailbox.
- Run it on the primary node only. Rows replicate and files sync (check Syncthing is up to date on both nodes).
- The mailboxes (voicemail_id = FreePBX mailbox number) must already exist in the FS PBX domain. Missing ones are listed in the pre-flight and skipped.
- Needs root, psql, ffmpeg or sox, and the default FS PBX paths (overridable with VM_ENV_FILE, VM_DEST_BASE, VM_WORKDIR).
- Greetings and recorded names. I did those by hand through the web UI.
- Voicemail PINs.
- Messages deleted or heard on FreePBX after an import are not synced afterwards.
- FreePBX: tar czf /tmp/vm.tgz -C /var/spool/asterisk/voicemail/default .
- Copy vm.tgz and vm-migrate.sh to /root on the FS PBX primary.
- chmod +x /root/vm-migrate.sh && /root/vm-migrate.sh
- Setup (pick archive and domain) -> Dry run -> Test one mailbox -> Full import -> Verify.