Migrating from Snipe-IT (and SnipeScheduler-FleetManager)
This guide is the canonical path for moving an existing deployment to Panorama. It covers both pure Snipe-IT installs and the SnipeScheduler-FleetManager overlay.
0. Decide your strategy
There are three ways in:
- Big-bang weekend migration — freeze writes on Snipe-IT, run the migrator, cutover, decommission. Appropriate for < 500 users.
- Parallel run with shim — run Panorama alongside Snipe-IT behind a Snipe-IT-compatible API shim (
/api/v1/hardwareetc.), let integrations keep calling the old URL while humans move to Panorama. Cutover when traffic tapers. - Read-replica initially — Panorama pulls from Snipe-IT continuously for N weeks, writes are still in Snipe-IT; staff get used to Panorama's UX, then you flip the write direction.
Most mid-size orgs should pick option 2.
1. Prerequisites
- Panorama v0.2 or later (reservations, migrator alpha)
- Snipe-IT v8.0 or later (API v1 with accepted-eula endpoint, multi-company flag)
- A Snipe-IT API token with a role that can read and write every entity you plan to migrate (usually Super Admin)
- For FleetManager overlay: a MySQL dump of the FleetManager database taken while no app server was running
2. Inventory
Before the first dry-run, take stock of what you have:
pnpm --filter @panorama/migrator cli inventory \
--snipeit-url https://snipe.example.com \
--snipeit-token $SNIPEIT_API_TOKEN \
--out ./inventory.jsoninventory.json lists every entity count and flags:
- Custom fields with non-portable validators (regex with Snipe-IT-specific flags)
- Users with duplicate emails (case-insensitive)
- Assets with status labels that don't match the bundled defaults
- Multi-company enabled but some users/assets have no company assigned
Fix anything flagged before running the actual migrator.
3. Dry run
pnpm --filter @panorama/migrator cli migrate \
--snipeit-url https://snipe.example.com \
--snipeit-token $SNIPEIT_API_TOKEN \
--fleetmanager-dump ./snipescheduler_backup.sql \
--out ./migrated \
--dry-run--dry-run writes Panorama fixture JSON files without touching any database. Audit the output:
- Asset / user / reservation counts match expectations
- No entity has
tenantId: null - Email addresses are all normalised to lowercase
- Custom fields preserve their values
4. Real migration
pnpm --filter @panorama/migrator cli migrate \
--snipeit-url https://snipe.example.com \
--snipeit-token $SNIPEIT_API_TOKEN \
--fleetmanager-dump ./snipescheduler_backup.sql \
--out ./migrated
# Then import into a fresh Panorama DB
pnpm --filter @panorama/core-api import-fixtures ./migratedImport runs in a single transaction per entity type. A failure rolls back without partial writes.
5. Compatibility shim
For option 2 (parallel run), enable the shim in core-api config:
COMPAT_SNIPEIT_API_ENABLED=true
COMPAT_SNIPEIT_READ_BACKING=panorama # or 'snipeit' during cutoverThe shim translates Snipe-IT's API v1 calls to Panorama native calls. It is a read/write proxy; each endpoint's parity status lives in apps/core-api/src/modules/compat-snipeit/README.md. Target parity:
- All
GETendpoints — v0.2 POST/PATCH /hardware,/users,/checkouts,/checkins— v0.3- Remaining writes — v0.4
6. Cutover checklist
- [ ] All integrations now point at Panorama (or at the shim URL)
- [ ] Drivers have been trained on the Panorama UI (at least a screen recording)
- [ ] Fleet Staff have practiced the approval queue in a sandbox tenant
- [ ] Snipe-IT is put in read-only mode (or write-disabled via network ACL)
- [ ] A final delta migrator run captures anything changed during the cutover window
- [ ] Panorama audit log has been inspected for the cutover window
- [ ] Old Snipe-IT backups retained for 90 days before decommission
7. What does NOT migrate
- Snipe-IT's stored user password hashes. Panorama uses Argon2id; we will force password resets via email link on first login if someone logs in with a non-SSO identity.
- Snipe-IT's API tokens (Passport). Re-issue fresh Panorama PATs.
- Spatie backup archives. Panorama's backup story uses Postgres PITR + object-store lifecycle rules (see
docs/en/ops-backup.mdonce it lands). - LDAP session cache. Users will re-authenticate once.
8. Rollback
If the cutover goes sideways:
- Flip the DNS back to Snipe-IT (it's still running read-only — flip it writable again)
- Run
panorama migrate-backto export any writes that hit Panorama during the cutover window into Snipe-IT API calls - Keep the Panorama install powered down but intact for post-mortem
This rollback path is drill-tested as part of the 1.0 release criteria.